This source file includes following definitions.
- it_char_has_category
- char_can_wrap_before
- char_can_wrap_after
- fill_column_indicator_column
- redisplay_other_windows
- wset_redisplay
- fset_redisplay
- bset_redisplay
- bset_update_mode_line
- wset_update_mode_line
- ATTRIBUTE_FORMAT_PRINTF
- ATTRIBUTE_FORMAT_PRINTF
- window_text_bottom_y
- window_box_width
- window_box_height
- window_box_left_offset
- window_box_right_offset
- window_box_left
- window_box_right
- window_box
- window_box_edges
- line_bottom_y
- DEFUN
- default_line_pixel_height
- string_from_display_spec
- window_hscroll_limited
- reset_box_start_end_flags
- pos_visible_p
- check_char_and_length
- string_pos_nchars_ahead
- string_pos
- c_string_pos
- number_of_chars
- compute_string_pos
- estimate_mode_line_height
- pixel_to_glyph_coords
- x_y_to_hpos_vpos
- frame_to_window_pixel_xy
- get_glyph_string_clip_rects
- get_glyph_string_clip_rect
- get_phys_cursor_geometry
- remember_mouse_glyph
- adjust_window_ends
- hscrolling_current_line_p
- safe_eval_handler
- safe__call
- safe_call
- safe_call1
- safe__call1
- safe_eval
- safe__eval
- safe_call2
- CHECK_IT
- CHECK_WINDOW_END
- init_iterator
- get_narrowed_width
- get_narrowed_len
- get_medium_narrowing_begv
- get_medium_narrowing_zv
- get_nearby_bol_pos
- get_small_narrowing_begv
- get_large_narrowing_begv
- get_large_narrowing_zv
- unwind_narrowed_begv
- start_display
- in_ellipses_for_invisible_text_p
- init_from_display_pos
- init_to_row_start
- init_to_row_end
- handle_stop
- compute_stop_pos
- compute_display_string_pos
- compute_display_string_end
- handle_fontified_prop
- face_at_pos
- handle_face_prop
- underlying_face_id
- face_before_or_after_it_pos
- handle_invisible_prop
- setup_for_ellipsis
- find_display_property
- get_display_property
- display_min_width
- handle_display_prop
- handle_display_spec
- display_prop_end
- handle_single_display_spec
- display_prop_intangible_p
- single_display_spec_string_p
- display_prop_string_p
- string_buffer_position_lim
- string_buffer_position
- handle_composition_prop
- handle_overlay_change
- next_overlay_string
- compare_overlay_entries
- load_overlay_strings
- get_overlay_strings_1
- get_overlay_strings
- push_it
- iterate_out_of_display_property
- restore_face_box_flags
- pop_it
- back_to_previous_line_start
- strings_with_newlines
- forward_to_next_line_start
- back_to_previous_visible_line_start
- reseat_at_previous_visible_line_start
- reseat_at_next_visible_line_start
- reseat
- reseat_1
- reseat_to_string
- lookup_glyphless_char_display
- merge_escape_glyph_face
- merge_glyphless_glyph_face
- forget_escape_and_glyphless_faces
- get_next_display_element
- set_iterator_to_next
- next_element_from_display_vector
- get_visually_first_element
- next_element_from_string
- next_element_from_c_string
- next_element_from_ellipsis
- next_element_from_image
- next_element_from_xwidget
- next_element_from_stretch
- compute_stop_pos_backwards
- handle_stop_backwards
- next_element_from_buffer
- next_element_from_composition
- move_it_in_display_line_to
- move_it_in_display_line
- move_it_to
- move_it_vertically_backward
- move_it_vertically
- move_it_past_eol
- move_it_by_lines
- partial_line_height
- fast_move_it_horizontally
- in_display_vector_p
- window_text_pixel_size
- DEFUN
- format_nargs
- add_to_log
- vadd_to_log
- message_log_maybe_newline
- message_dolog
- message_log_check_duplicate
- message3
- message_to_stderr
- message3_nolog
- message1
- message1_nolog
- message_with_string
- ATTRIBUTE_FORMAT_PRINTF
- message
- update_echo_area
- ensure_echo_area_buffers
- with_echo_area_buffer
- with_echo_area_buffer_unwind_data
- unwind_with_echo_area_buffer
- setup_echo_area_for_printing
- display_echo_area
- display_echo_area_1
- resize_echo_area_exactly
- resize_mini_window_1
- resize_mini_window
- current_message
- current_message_1
- push_message
- restore_message
- pop_message_unwind
- check_message_stack
- clear_message_stack
- truncate_echo_area
- truncate_message_1
- set_message
- set_message_1
- clear_message
- clear_garbaged_frames
- echo_area_display
- window_buffer_changed
- mode_line_update_needed
- window_frozen_p
- format_mode_line_unwind_data
- unwind_format_mode_line
- store_mode_line_noprop_char
- store_mode_line_noprop
- gui_consider_frame_title
- needs_no_redisplay
- prepare_menu_bars
- update_menu_bar
- restore_selected_window
- restore_frame_selected_window
- update_tab_bar
- display_tab_bar
- build_desired_tab_bar_string
- display_tab_bar_line
- tab_bar_height
- redisplay_tab_bar
- tab_bar_item_info
- get_tab_bar_item
- get_tab_bar_item_kbd
- handle_tab_bar_click
- note_tab_bar_highlight
- tty_get_tab_bar_item
- tty_handle_tab_bar_click
- update_tool_bar
- build_desired_tool_bar_string
- display_tool_bar_line
- tool_bar_height
- redisplay_tool_bar
- tool_bar_item_info
- get_tool_bar_item
- handle_tool_bar_click_with_device
- handle_tool_bar_click
- note_tool_bar_highlight
- hscroll_window_tree
- hscroll_windows
- debug_method_add
- text_outside_line_unchanged_p
- redisplay
- overlay_arrow_string_or_property
- overlay_arrow_in_current_buffer_p
- overlay_arrows_changed_p
- update_overlay_arrows
- overlay_arrow_at_row
- check_point_in_composition
- reconsider_clip_changes
- propagate_buffer_redisplay
- redisplay_internal
- unwind_redisplay_preserve_echo_area
- redisplay_preserve_echo_area
- unwind_redisplay
- unwind_display_working_on_window
- mark_window_display_accurate_1
- mark_window_display_accurate
- disp_char_vector
- block_buffer_flips
- unblock_buffer_flips
- buffer_flipping_blocked_p
- redisplay_windows
- redisplay_window_error
- redisplay_window_0
- redisplay_window_1
- update_redisplay_ticks
- set_cursor_from_row
- run_window_scroll_functions
- cursor_row_fully_visible_p
- try_scrolling
- compute_window_start_on_continuation_line
- try_cursor_movement
- set_vertical_scroll_bar
- set_horizontal_scroll_bar
- window_start_acceptable_p
- DEFUN
- redisplay_window
- try_window
- try_window_reusing_current_matrix
- find_last_row_displaying_text
- find_last_unchanged_at_beg_row
- find_first_unchanged_at_end_row
- sync_frame_with_window_matrix_rows
- row_containing_pos
- try_window_id
- dump_glyph_row
- dump_glyph
- dump_glyph_row
- DEFUN
- DEFUN
- DEFUN
- get_overlay_arrow_glyph_row
- insert_left_trunc_glyphs
- row_hash
- compute_line_metrics
- clear_position
- append_space_for_newline
- extend_face_to_end_of_line
- trailing_whitespace_p
- highlight_trailing_whitespace
- row_for_charpos_p
- cursor_row_p
- push_prefix_prop
- get_it_property
- get_line_prefix_it_property
- handle_line_prefix
- unproduce_glyphs
- find_row_edges
- display_count_lines_logically
- display_count_lines_visually
- maybe_produce_line_number
- should_produce_line_number
- row_text_area_empty
- display_line
- DEFUN
- DEFUN
- DEFUN
- display_menu_bar
- deep_copy_glyph_row
- display_tty_menu_item
- redisplay_mode_lines
- display_mode_lines
- display_mode_line
- move_elt_to_front
- safe_set_text_properties
- display_mode_element
- store_mode_line_string
- pint2str
- pint2hrstr
- decode_mode_spec_coding
- percent99
- decode_mode_spec
- count_lines
- display_count_lines
- display_string
- invisible_prop
- DEFUN
- calc_pixel_width_or_height
- get_font_ascent_descent
- dump_glyph_string
- init_glyph_string
- append_glyph_string_lists
- prepend_glyph_string_lists
- append_glyph_string
- get_char_face_and_encoding
- get_glyph_face_and_encoding
- get_char_glyph_code
- fill_composite_glyph_string
- fill_gstring_glyph_string
- fill_glyphless_glyph_string
- fill_glyph_string
- fill_image_glyph_string
- fill_xwidget_glyph_string
- fill_stretch_glyph_string
- get_per_char_metric
- normal_char_ascent_descent
- normal_char_height
- gui_get_glyph_overhangs
- left_overwritten
- left_overwriting
- right_overwritten
- right_overwriting
- set_glyph_string_background_width
- glyph_string_containing_background_width
- compute_overhangs_and_x
- draw_glyphs
- font_for_underline_metrics
- append_glyph
- append_composite_glyph
- take_vertical_position_into_account
- produce_image_glyph
- produce_xwidget_glyph
- append_stretch_glyph
- produce_stretch_glyph
- produce_special_glyphs
- pad_mode_line
- calc_line_height_property
- append_glyphless_glyph
- produce_glyphless_glyph
- gui_produce_glyphs
- gui_write_glyphs
- gui_insert_glyphs
- gui_clear_end_of_line
- get_specified_cursor_type
- set_frame_cursor_types
- get_window_cursor_type
- notice_overwritten_cursor
- gui_fix_overlapping_area
- draw_phys_cursor_glyph
- erase_phys_cursor
- display_and_set_cursor
- update_window_cursor
- update_cursor_in_window_tree
- gui_update_cursor
- gui_clear_cursor
- draw_row_with_mouse_face
- show_mouse_face
- clear_mouse_face
- coords_in_mouse_face_p
- cursor_in_mouse_face_p
- rows_from_pos_range
- mouse_face_from_buffer_pos
- fast_find_string_pos
- mouse_face_from_string_pos
- on_hot_spot_p
- find_hot_spot
- define_frame_cursor1
- note_mode_line_or_margin_highlight
- note_mouse_highlight
- gui_clear_window_mouse_face
- cancel_mouse_face
- expose_area
- expose_line
- expose_overlaps
- phys_cursor_in_rect_p
- gui_draw_vertical_border
- gui_draw_right_divider
- gui_draw_bottom_divider
- expose_window
- expose_window_tree
- expose_frame
- gui_intersect_rectangles
- gui_union_rectangles
- syms_of_xdisp
- init_xdisp
- show_hourglass
- start_hourglass
- cancel_hourglass
- adjust_glyph_width_for_mouse_face
- get_cursor_offset_for_mouse_face
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468 #include <config.h>
469 #include <stdlib.h>
470 #include <limits.h>
471 #include <math.h>
472
473 #include "lisp.h"
474 #include "atimer.h"
475 #include "composite.h"
476 #include "keyboard.h"
477 #include "sysstdio.h"
478 #include "systime.h"
479 #include "frame.h"
480 #include "window.h"
481 #include "termchar.h"
482 #include "dispextern.h"
483 #include "character.h"
484 #include "category.h"
485 #include "buffer.h"
486 #include "charset.h"
487 #include "indent.h"
488 #include "commands.h"
489 #include "keymap.h"
490 #include "disptab.h"
491 #include "termhooks.h"
492 #include "termopts.h"
493 #include "intervals.h"
494 #include "coding.h"
495 #include "region-cache.h"
496 #include "font.h"
497 #include "fontset.h"
498 #include "blockinput.h"
499 #include "xwidget.h"
500 #ifdef HAVE_WINDOW_SYSTEM
501 #include TERM_HEADER
502 #endif
503
504 #ifndef FRAME_OUTPUT_DATA
505 #define FRAME_OUTPUT_DATA(f) (NULL)
506 #endif
507
508 #define DISP_INFINITY 10000000
509
510
511 static Lisp_Object list_of_error;
512
513 #ifdef HAVE_WINDOW_SYSTEM
514
515
516
517
518 #define IT_OVERFLOW_NEWLINE_INTO_FRINGE(IT) \
519 (!NILP (Voverflow_newline_into_fringe) \
520 && FRAME_WINDOW_P ((IT)->f) \
521 && ((IT)->bidi_it.paragraph_dir == R2L \
522 ? (WINDOW_LEFT_FRINGE_WIDTH ((IT)->w) > 0) \
523 : (WINDOW_RIGHT_FRINGE_WIDTH ((IT)->w) > 0)) \
524 && (IT)->current_x == (IT)->last_visible_x)
525
526 #else
527 #define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it) false
528 #endif
529
530
531
532
533
534 #define IT_DISPLAYING_WHITESPACE(it) \
535 ((it->what == IT_CHARACTER && (it->c == ' ' || it->c == '\t')) \
536 || ((STRINGP (it->string) \
537 && (SREF (it->string, IT_STRING_BYTEPOS (*it)) == ' ' \
538 || SREF (it->string, IT_STRING_BYTEPOS (*it)) == '\t')) \
539 || (it->s \
540 && (it->s[IT_BYTEPOS (*it)] == ' ' \
541 || it->s[IT_BYTEPOS (*it)] == '\t')) \
542 || (IT_BYTEPOS (*it) < ZV_BYTE \
543 && (*BYTE_POS_ADDR (IT_BYTEPOS (*it)) == ' ' \
544 || *BYTE_POS_ADDR (IT_BYTEPOS (*it)) == '\t'))))
545
546
547
548 #define NOT_AT_EOL '<'
549 #define NOT_AT_BOL '>'
550 #define LINE_BREAKABLE '|'
551
552 static bool
553 it_char_has_category(struct it *it, int cat)
554 {
555 int ch = 0;
556 if (it->what == IT_CHARACTER)
557 ch = it->c;
558 else if (STRINGP (it->string))
559 ch = SREF (it->string, IT_STRING_BYTEPOS (*it));
560 else if (it->s)
561 ch = it->s[IT_BYTEPOS (*it)];
562 else if (IT_BYTEPOS (*it) < ZV_BYTE)
563 ch = *BYTE_POS_ADDR (IT_BYTEPOS (*it));
564
565 if (ch == 0)
566 return false;
567 else
568 return CHAR_HAS_CATEGORY (ch, cat);
569 }
570
571
572 static bool
573 char_can_wrap_before (struct it *it)
574 {
575 if (!word_wrap_by_category)
576 return !IT_DISPLAYING_WHITESPACE (it);
577
578
579
580
581 int not_at_bol;
582 if (it->glyph_row && it->glyph_row->reversed_p)
583 not_at_bol = NOT_AT_EOL;
584 else
585 not_at_bol = NOT_AT_BOL;
586
587
588 return (!IT_DISPLAYING_WHITESPACE (it)
589
590 && !it_char_has_category (it, not_at_bol));
591 }
592
593
594 static bool
595 char_can_wrap_after (struct it *it)
596 {
597 if (!word_wrap_by_category)
598 return IT_DISPLAYING_WHITESPACE (it);
599
600
601
602
603 int not_at_eol;
604 if (it->glyph_row && it->glyph_row->reversed_p)
605 not_at_eol = NOT_AT_BOL;
606 else
607 not_at_eol = NOT_AT_EOL;
608
609 return (IT_DISPLAYING_WHITESPACE (it)
610
611 || (it_char_has_category (it, LINE_BREAKABLE)
612 && !it_char_has_category (it, not_at_eol)));
613 }
614
615 #undef IT_DISPLAYING_WHITESPACE
616 #undef NOT_AT_EOL
617 #undef NOT_AT_BOL
618 #undef LINE_BREAKABLE
619
620
621
622
623 static int
624 fill_column_indicator_column (struct it *it, int char_width)
625 {
626 if (display_fill_column_indicator
627 && !it->w->pseudo_window_p
628 && it->continuation_lines_width == 0
629 && CHARACTERP (Vdisplay_fill_column_indicator_character))
630 {
631 Lisp_Object col = (EQ (Vdisplay_fill_column_indicator_column, Qt)
632 ? BVAR (current_buffer, fill_column)
633 : Vdisplay_fill_column_indicator_column);
634
635
636
637 if (RANGED_FIXNUMP (0, col, INT_MAX))
638 {
639 int icol = XFIXNUM (col);
640 if (!ckd_mul (&icol, icol, char_width)
641 && !ckd_add (&icol, icol, it->lnum_pixel_width))
642 return icol;
643 }
644 }
645 return -1;
646 }
647
648
649
650 bool noninteractive_need_newline;
651
652
653
654 static bool message_log_need_newline;
655
656
657
658
659 static Lisp_Object message_dolog_marker1;
660 static Lisp_Object message_dolog_marker2;
661 static Lisp_Object message_dolog_marker3;
662
663
664
665
666
667
668 static struct text_pos this_line_start_pos;
669
670
671
672
673 static struct text_pos this_line_end_pos;
674
675
676
677 static int this_line_vpos;
678 static int this_line_y;
679 static int this_line_pixel_height;
680
681
682
683
684 static int this_line_start_x;
685
686
687
688
689
690 static struct text_pos this_line_min_pos;
691
692
693
694 static struct buffer *this_line_buffer;
695
696
697
698 static bool overlay_arrow_seen;
699
700
701
702 static Lisp_Object default_invis_vector[3];
703
704
705
706
707
708 Lisp_Object echo_area_window;
709
710
711
712
713 static Lisp_Object Vmessage_stack;
714
715
716
717
718 static bool message_enable_multibyte;
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750 int windows_or_buffers_changed;
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771 int update_mode_lines;
772
773
774
775
776 static bool line_number_displayed;
777
778
779
780
781 Lisp_Object echo_area_buffer[2];
782
783
784
785 static Lisp_Object echo_buffer[2];
786
787
788
789 static Lisp_Object Vwith_echo_area_save_vector;
790
791
792
793
794 static bool display_last_displayed_message_p;
795
796
797
798
799 static bool message_buf_print;
800
801
802
803
804 static bool message_cleared_p;
805
806
807
808
809 #define MAX_SCRATCH_GLYPHS 100
810 static struct glyph_row scratch_glyph_row;
811 static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
812
813
814
815 static int last_height;
816
817
818
819 bool help_echo_showing_p;
820
821
822
823
824
825
826
827 #define TEXT_PROP_DISTANCE_LIMIT 100
828
829
830
831
832
833
834
835
836 #define SAVE_IT(ITCOPY, ITORIG, CACHE) \
837 do { \
838 if (CACHE) \
839 bidi_unshelve_cache (CACHE, true); \
840 ITCOPY = ITORIG; \
841 CACHE = bidi_shelve_cache (); \
842 } while (false)
843
844 #define RESTORE_IT(pITORIG, pITCOPY, CACHE) \
845 do { \
846 if (pITORIG != pITCOPY) \
847 *(pITORIG) = *(pITCOPY); \
848 bidi_unshelve_cache (CACHE, false); \
849 CACHE = NULL; \
850 } while (false)
851
852
853 enum { REDISPLAY_SOME = 2};
854
855 static bool calc_pixel_width_or_height (double *, struct it *, Lisp_Object,
856 struct font *, bool, int *);
857
858 void
859 redisplay_other_windows (void)
860 {
861 if (!windows_or_buffers_changed)
862 windows_or_buffers_changed = REDISPLAY_SOME;
863 }
864
865 void
866 wset_redisplay (struct window *w)
867 {
868
869 if (!BASE_EQ (make_lisp_ptr (w, Lisp_Vectorlike), selected_window))
870 redisplay_other_windows ();
871 w->redisplay = true;
872 }
873
874 void
875 fset_redisplay (struct frame *f)
876 {
877 redisplay_other_windows ();
878 f->redisplay = true;
879 }
880
881 void
882 bset_redisplay (struct buffer *b)
883 {
884 int count = buffer_window_count (b);
885 if (count > 0)
886 {
887
888 if (count > 1 || b != XBUFFER (XWINDOW (selected_window)->contents))
889 redisplay_other_windows ();
890
891
892
893 b->text->redisplay = true;
894 }
895 }
896
897 void
898 bset_update_mode_line (struct buffer *b)
899 {
900 if (!update_mode_lines)
901 update_mode_lines = REDISPLAY_SOME;
902 b->text->redisplay = true;
903 }
904
905 void
906 wset_update_mode_line (struct window *w)
907 {
908 w->update_mode_line = true;
909
910
911
912
913
914
915 wset_redisplay (w);
916 }
917
918 DEFUN ("set-buffer-redisplay", Fset_buffer_redisplay,
919 Sset_buffer_redisplay, 4, 4, 0,
920 doc:
921 )
922 (Lisp_Object symbol, Lisp_Object newval, Lisp_Object op, Lisp_Object where)
923 {
924 bset_update_mode_line (current_buffer);
925 current_buffer->prevent_redisplay_optimizations_p = true;
926 return Qnil;
927 }
928
929
930
931
932
933 #ifdef GLYPH_DEBUG
934 extern bool trace_redisplay_p EXTERNALLY_VISIBLE;
935 bool trace_redisplay_p;
936 #else
937 enum { trace_redisplay_p = false };
938 #endif
939 static void ATTRIBUTE_FORMAT_PRINTF (1, 2)
940 redisplay_trace (char const *fmt, ...)
941 {
942 if (trace_redisplay_p)
943 {
944 va_list ap;
945 va_start (ap, fmt);
946 vprintf (fmt, ap);
947 va_end (ap);
948 }
949 }
950
951 #ifdef DEBUG_TRACE_MOVE
952 extern bool trace_move EXTERNALLY_VISIBLE;
953 bool trace_move;
954 #else
955 enum { trace_move = false };
956 #endif
957 static void ATTRIBUTE_FORMAT_PRINTF (1, 2)
958 move_trace (char const *fmt, ...)
959 {
960 if (trace_move)
961 {
962 va_list ap;
963 va_start (ap, fmt);
964 vprintf (fmt, ap);
965 va_end (ap);
966 }
967 }
968
969
970
971 static struct buffer *displayed_buffer;
972
973
974
975 enum prop_handled
976 {
977 HANDLED_NORMALLY,
978 HANDLED_RECOMPUTE_PROPS,
979 HANDLED_OVERLAY_STRING_CONSUMED,
980 HANDLED_RETURN
981 };
982
983
984
985
986 struct props
987 {
988
989 short name;
990
991
992 enum prop_idx idx;
993
994
995
996 enum prop_handled (*handler) (struct it *it);
997 };
998
999 static enum prop_handled handle_face_prop (struct it *);
1000 static enum prop_handled handle_invisible_prop (struct it *);
1001 static enum prop_handled handle_display_prop (struct it *);
1002 static enum prop_handled handle_composition_prop (struct it *);
1003 static enum prop_handled handle_overlay_change (struct it *);
1004 static enum prop_handled handle_fontified_prop (struct it *);
1005
1006
1007
1008 static struct props it_props[] =
1009 {
1010 {SYMBOL_INDEX (Qfontified), FONTIFIED_PROP_IDX, handle_fontified_prop},
1011
1012
1013 {SYMBOL_INDEX (Qface), FACE_PROP_IDX, handle_face_prop},
1014 {SYMBOL_INDEX (Qdisplay), DISPLAY_PROP_IDX, handle_display_prop},
1015 {SYMBOL_INDEX (Qinvisible), INVISIBLE_PROP_IDX, handle_invisible_prop},
1016 {SYMBOL_INDEX (Qcomposition), COMPOSITION_PROP_IDX, handle_composition_prop},
1017 {0, 0, NULL}
1018 };
1019
1020
1021
1022 enum move_it_result
1023 {
1024
1025 MOVE_UNDEFINED,
1026
1027
1028 MOVE_POS_MATCH_OR_ZV,
1029
1030
1031 MOVE_X_REACHED,
1032
1033
1034
1035 MOVE_LINE_CONTINUED,
1036
1037
1038
1039 MOVE_LINE_TRUNCATED,
1040
1041
1042 MOVE_NEWLINE_OR_CR
1043 };
1044
1045
1046
1047
1048
1049
1050 #define CLEAR_FACE_CACHE_COUNT 500
1051 static int clear_face_cache_count;
1052
1053
1054
1055 #ifdef HAVE_WINDOW_SYSTEM
1056 #define CLEAR_IMAGE_CACHE_COUNT 101
1057 static int clear_image_cache_count;
1058
1059
1060 static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
1061 #endif
1062
1063
1064
1065 bool redisplaying_p;
1066
1067
1068
1069
1070
1071
1072
1073
1074 bool display_working_on_window_p;
1075
1076
1077
1078
1079 Lisp_Object help_echo_string;
1080 Lisp_Object help_echo_window;
1081 Lisp_Object help_echo_object;
1082 ptrdiff_t help_echo_pos;
1083
1084
1085
1086 Lisp_Object previous_help_echo_string;
1087
1088
1089
1090 #ifdef HAVE_WINDOW_SYSTEM
1091
1092
1093 static bool hourglass_shown_p;
1094
1095
1096
1097 static struct atimer *hourglass_atimer;
1098
1099 #endif
1100
1101
1102
1103 #define DEFAULT_HOURGLASS_DELAY 1
1104
1105 #ifdef HAVE_WINDOW_SYSTEM
1106
1107
1108 #define THIN_SPACE_WIDTH 1
1109
1110 #endif
1111
1112
1113
1114 static void setup_for_ellipsis (struct it *, int);
1115 static void set_iterator_to_next (struct it *, bool);
1116 static void mark_window_display_accurate_1 (struct window *, bool);
1117 static bool row_for_charpos_p (struct glyph_row *, ptrdiff_t);
1118 static bool cursor_row_p (struct glyph_row *);
1119 static int redisplay_mode_lines (Lisp_Object, bool);
1120
1121 static void handle_line_prefix (struct it *);
1122
1123 static void handle_stop_backwards (struct it *, ptrdiff_t);
1124 static void unwind_with_echo_area_buffer (Lisp_Object);
1125 static Lisp_Object with_echo_area_buffer_unwind_data (struct window *);
1126 static bool current_message_1 (void *, Lisp_Object);
1127 static bool truncate_message_1 (void *, Lisp_Object);
1128 static void set_message (Lisp_Object);
1129 static bool set_message_1 (void *, Lisp_Object);
1130 static bool display_echo_area_1 (void *, Lisp_Object);
1131 static bool resize_mini_window_1 (void *, Lisp_Object);
1132 static void unwind_redisplay (void);
1133 static void extend_face_to_end_of_line (struct it *);
1134 static intmax_t message_log_check_duplicate (ptrdiff_t, ptrdiff_t);
1135 static void push_it (struct it *, struct text_pos *);
1136 static void iterate_out_of_display_property (struct it *);
1137 static void pop_it (struct it *);
1138 static void redisplay_internal (void);
1139 static void echo_area_display (bool);
1140 static void block_buffer_flips (void);
1141 static void unblock_buffer_flips (void);
1142 static void redisplay_windows (Lisp_Object);
1143 static void redisplay_window (Lisp_Object, bool);
1144 static Lisp_Object redisplay_window_error (Lisp_Object);
1145 static Lisp_Object redisplay_window_0 (Lisp_Object);
1146 static Lisp_Object redisplay_window_1 (Lisp_Object);
1147 static bool set_cursor_from_row (struct window *, struct glyph_row *,
1148 struct glyph_matrix *, ptrdiff_t, ptrdiff_t,
1149 int, int);
1150 static bool cursor_row_fully_visible_p (struct window *, bool, bool, bool);
1151 static bool update_menu_bar (struct frame *, bool, bool);
1152 static bool try_window_reusing_current_matrix (struct window *);
1153 static int try_window_id (struct window *);
1154 static void maybe_produce_line_number (struct it *);
1155 static bool should_produce_line_number (struct it *);
1156 static bool display_line (struct it *, int);
1157 static int display_mode_lines (struct window *);
1158 static int display_mode_line (struct window *, enum face_id, Lisp_Object);
1159 static int display_mode_element (struct it *, int, int, int, Lisp_Object,
1160 Lisp_Object, bool);
1161 static int store_mode_line_string (const char *, Lisp_Object, bool, int, int,
1162 Lisp_Object);
1163 static const char *decode_mode_spec (struct window *, int, int, Lisp_Object *);
1164 static void display_menu_bar (struct window *);
1165 static void display_tab_bar (struct window *);
1166 static void update_tab_bar (struct frame *, bool);
1167 static ptrdiff_t display_count_lines (ptrdiff_t, ptrdiff_t, ptrdiff_t,
1168 ptrdiff_t *);
1169 static void pint2str (register char *, register int, register ptrdiff_t);
1170
1171 static int display_string (const char *, Lisp_Object, Lisp_Object,
1172 ptrdiff_t, ptrdiff_t, struct it *, int, int, int,
1173 int);
1174 static void compute_line_metrics (struct it *);
1175 static bool get_overlay_strings (struct it *, ptrdiff_t);
1176 static bool get_overlay_strings_1 (struct it *, ptrdiff_t, bool);
1177 static void next_overlay_string (struct it *);
1178 static void reseat (struct it *, struct text_pos, bool);
1179 static void reseat_1 (struct it *, struct text_pos, bool);
1180 static bool next_element_from_display_vector (struct it *);
1181 static bool next_element_from_string (struct it *);
1182 static bool next_element_from_c_string (struct it *);
1183 static bool next_element_from_buffer (struct it *);
1184 static bool next_element_from_composition (struct it *);
1185 static bool next_element_from_image (struct it *);
1186 static bool next_element_from_stretch (struct it *);
1187 static bool next_element_from_xwidget (struct it *);
1188 static void load_overlay_strings (struct it *, ptrdiff_t);
1189 static bool get_next_display_element (struct it *);
1190 static enum move_it_result
1191 move_it_in_display_line_to (struct it *, ptrdiff_t, int,
1192 enum move_operation_enum);
1193 static void get_visually_first_element (struct it *);
1194 static void compute_stop_pos (struct it *);
1195 static int face_before_or_after_it_pos (struct it *, bool);
1196 static int handle_display_spec (struct it *, Lisp_Object, Lisp_Object,
1197 Lisp_Object, struct text_pos *, ptrdiff_t, bool);
1198 static int handle_single_display_spec (struct it *, Lisp_Object, Lisp_Object,
1199 Lisp_Object, struct text_pos *,
1200 ptrdiff_t, int, bool, bool);
1201 static int underlying_face_id (const struct it *);
1202
1203 #define face_before_it_pos(IT) face_before_or_after_it_pos (IT, true)
1204 #define face_after_it_pos(IT) face_before_or_after_it_pos (IT, false)
1205
1206 #ifdef HAVE_WINDOW_SYSTEM
1207
1208 static void update_tool_bar (struct frame *, bool);
1209 static void gui_draw_bottom_divider (struct window *w);
1210 static void notice_overwritten_cursor (struct window *,
1211 enum glyph_row_area,
1212 int, int, int, int);
1213 static int normal_char_height (struct font *, int);
1214 static void normal_char_ascent_descent (struct font *, int, int *, int *);
1215
1216 static void append_stretch_glyph (struct it *, Lisp_Object,
1217 int, int, int);
1218
1219 static Lisp_Object get_it_property (struct it *, Lisp_Object);
1220 static Lisp_Object calc_line_height_property (struct it *, Lisp_Object,
1221 struct font *, int, bool);
1222 static int adjust_glyph_width_for_mouse_face (struct glyph *,
1223 struct glyph_row *,
1224 struct window *, struct face *,
1225 struct face *);
1226 static void get_cursor_offset_for_mouse_face (struct window *w,
1227 struct glyph_row *row,
1228 int *offset);
1229 #endif
1230
1231 static void produce_special_glyphs (struct it *, enum display_element_type);
1232 static void pad_mode_line (struct it *, bool);
1233 static void show_mouse_face (Mouse_HLInfo *, enum draw_glyphs_face);
1234 static bool coords_in_mouse_face_p (struct window *, int, int);
1235 static void reset_box_start_end_flags (struct it *);
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249 int
1250 window_text_bottom_y (struct window *w)
1251 {
1252 int height = WINDOW_PIXEL_HEIGHT (w);
1253
1254 height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
1255
1256 if (window_wants_mode_line (w))
1257 height -= CURRENT_MODE_LINE_HEIGHT (w);
1258
1259 height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
1260
1261 return height;
1262 }
1263
1264
1265
1266
1267
1268 int
1269 window_box_width (struct window *w, enum glyph_row_area area)
1270 {
1271 int width = w->pixel_width;
1272
1273 if (!w->pseudo_window_p)
1274 {
1275 width -= WINDOW_SCROLL_BAR_AREA_WIDTH (w);
1276 width -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
1277
1278 if (area == TEXT_AREA)
1279 width -= (WINDOW_MARGINS_WIDTH (w)
1280 + WINDOW_FRINGES_WIDTH (w));
1281 else if (area == LEFT_MARGIN_AREA)
1282 width = WINDOW_LEFT_MARGIN_WIDTH (w);
1283 else if (area == RIGHT_MARGIN_AREA)
1284 width = WINDOW_RIGHT_MARGIN_WIDTH (w);
1285 }
1286
1287
1288
1289 return max (0, width);
1290 }
1291
1292
1293
1294
1295
1296 int
1297 window_box_height (struct window *w)
1298 {
1299 struct frame *f = XFRAME (w->frame);
1300 int height = WINDOW_PIXEL_HEIGHT (w);
1301
1302 eassert (height >= 0);
1303
1304 height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
1305 height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
1306
1307
1308
1309
1310
1311
1312
1313 if (window_wants_mode_line (w))
1314 {
1315 if (w->mode_line_height >= 0)
1316 height -= w->mode_line_height;
1317 else
1318 {
1319 struct glyph_row *ml_row
1320 = (w->current_matrix && w->current_matrix->rows
1321 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
1322 : 0);
1323 if (ml_row && ml_row->mode_line_p)
1324 height -= ml_row->height;
1325 else
1326 height -= estimate_mode_line_height
1327 (f, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w));
1328 }
1329 }
1330
1331 if (window_wants_tab_line (w))
1332 {
1333 if (w->tab_line_height >= 0)
1334 height -= w->tab_line_height;
1335 else
1336 {
1337 struct glyph_row *tl_row
1338 = (w->current_matrix && w->current_matrix->rows
1339 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
1340 : 0);
1341 if (tl_row && tl_row->mode_line_p)
1342 height -= tl_row->height;
1343 else
1344 height -= estimate_mode_line_height (f, TAB_LINE_FACE_ID);
1345 }
1346 }
1347
1348 if (window_wants_header_line (w))
1349 {
1350 if (w->header_line_height >= 0)
1351 height -= w->header_line_height;
1352 else
1353 {
1354 struct glyph_row *hl_row
1355 = (w->current_matrix && w->current_matrix->rows
1356 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
1357 : 0);
1358 if (hl_row && hl_row->mode_line_p)
1359 height -= hl_row->height;
1360 else
1361 height -= estimate_mode_line_height (f, HEADER_LINE_FACE_ID);
1362 }
1363 }
1364
1365
1366
1367 return max (0, height);
1368 }
1369
1370
1371
1372
1373
1374 int
1375 window_box_left_offset (struct window *w, enum glyph_row_area area)
1376 {
1377 int x;
1378
1379 if (w->pseudo_window_p)
1380 return 0;
1381
1382 x = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
1383
1384 if (area == TEXT_AREA)
1385 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1386 + window_box_width (w, LEFT_MARGIN_AREA));
1387 else if (area == RIGHT_MARGIN_AREA)
1388 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1389 + window_box_width (w, LEFT_MARGIN_AREA)
1390 + window_box_width (w, TEXT_AREA)
1391 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1392 ? 0
1393 : WINDOW_RIGHT_FRINGE_WIDTH (w)));
1394 else if (area == LEFT_MARGIN_AREA
1395 && WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1396 x += WINDOW_LEFT_FRINGE_WIDTH (w);
1397
1398
1399 return min (x, w->pixel_width);
1400 }
1401
1402
1403
1404
1405
1406
1407 static int
1408 window_box_right_offset (struct window *w, enum glyph_row_area area)
1409 {
1410
1411 return min (window_box_left_offset (w, area) + window_box_width (w, area),
1412 w->pixel_width);
1413 }
1414
1415
1416
1417
1418
1419 int
1420 window_box_left (struct window *w, enum glyph_row_area area)
1421 {
1422 struct frame *f = XFRAME (w->frame);
1423 int x;
1424
1425 if (w->pseudo_window_p)
1426 return FRAME_INTERNAL_BORDER_WIDTH (f);
1427
1428 x = (WINDOW_LEFT_EDGE_X (w)
1429 + window_box_left_offset (w, area));
1430
1431 return x;
1432 }
1433
1434
1435
1436
1437
1438
1439 int
1440 window_box_right (struct window *w, enum glyph_row_area area)
1441 {
1442 return window_box_left (w, area) + window_box_width (w, area);
1443 }
1444
1445
1446
1447
1448
1449
1450
1451
1452 void
1453 window_box (struct window *w, enum glyph_row_area area, int *box_x,
1454 int *box_y, int *box_width, int *box_height)
1455 {
1456 if (box_width)
1457 *box_width = window_box_width (w, area);
1458 if (box_height)
1459 *box_height = window_box_height (w);
1460 if (box_x)
1461 *box_x = window_box_left (w, area);
1462 if (box_y)
1463 {
1464 *box_y = WINDOW_TOP_EDGE_Y (w);
1465 if (window_wants_tab_line (w))
1466 *box_y += CURRENT_TAB_LINE_HEIGHT (w);
1467 if (window_wants_header_line (w))
1468 *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
1469 }
1470 }
1471
1472 #ifdef HAVE_WINDOW_SYSTEM
1473
1474
1475
1476
1477
1478
1479
1480
1481 static void
1482 window_box_edges (struct window *w, int *top_left_x, int *top_left_y,
1483 int *bottom_right_x, int *bottom_right_y)
1484 {
1485 window_box (w, ANY_AREA, top_left_x, top_left_y,
1486 bottom_right_x, bottom_right_y);
1487 *bottom_right_x += *top_left_x;
1488 *bottom_right_y += *top_left_y;
1489 }
1490
1491 #endif
1492
1493
1494
1495
1496
1497
1498
1499
1500 int
1501 line_bottom_y (struct it *it)
1502 {
1503 int line_height = it->max_ascent + it->max_descent;
1504 int line_top_y = it->current_y;
1505
1506 if (line_height == 0)
1507 {
1508 if (last_height)
1509 line_height = last_height;
1510 else if (IT_CHARPOS (*it) < ZV)
1511 {
1512 move_it_by_lines (it, 1);
1513 line_height = (it->max_ascent || it->max_descent
1514 ? it->max_ascent + it->max_descent
1515 : last_height);
1516 }
1517 else
1518 {
1519 struct glyph_row *row = it->glyph_row;
1520
1521
1522 it->glyph_row = NULL;
1523 it->what = IT_CHARACTER;
1524 it->c = ' ';
1525 it->len = 1;
1526 PRODUCE_GLYPHS (it);
1527 line_height = it->ascent + it->descent;
1528 it->glyph_row = row;
1529 }
1530 }
1531
1532 return line_top_y + line_height;
1533 }
1534
1535 DEFUN ("line-pixel-height", Fline_pixel_height,
1536 Sline_pixel_height, 0, 0, 0,
1537 doc:
1538
1539 )
1540 (void)
1541 {
1542 struct it it;
1543 struct text_pos pt;
1544 struct window *w = XWINDOW (selected_window);
1545 struct buffer *old_buffer = NULL;
1546 Lisp_Object result;
1547
1548 if (XBUFFER (w->contents) != current_buffer)
1549 {
1550 old_buffer = current_buffer;
1551 set_buffer_internal_1 (XBUFFER (w->contents));
1552 }
1553 SET_TEXT_POS (pt, PT, PT_BYTE);
1554 void *itdata = bidi_shelve_cache ();
1555 start_display (&it, w, pt);
1556
1557
1558
1559 move_it_by_lines (&it, 0);
1560 it.vpos = it.current_y = 0;
1561 last_height = 0;
1562 result = make_fixnum (line_bottom_y (&it));
1563 if (old_buffer)
1564 set_buffer_internal_1 (old_buffer);
1565
1566 bidi_unshelve_cache (itdata, false);
1567 return result;
1568 }
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584 int
1585 default_line_pixel_height (struct window *w)
1586 {
1587 struct frame *f = WINDOW_XFRAME (w);
1588 int height = FRAME_LINE_HEIGHT (f);
1589
1590 if (!FRAME_INITIAL_P (f) && BUFFERP (w->contents))
1591 {
1592 struct buffer *b = XBUFFER (w->contents);
1593 Lisp_Object val = BVAR (b, extra_line_spacing);
1594
1595 if (NILP (val))
1596 val = BVAR (&buffer_defaults, extra_line_spacing);
1597 if (!NILP (val))
1598 {
1599 if (RANGED_FIXNUMP (0, val, INT_MAX))
1600 height += XFIXNAT (val);
1601 else if (FLOATP (val))
1602 {
1603 int addon = XFLOAT_DATA (val) * height + 0.5;
1604
1605 if (addon >= 0)
1606 height += addon;
1607 }
1608 }
1609 else
1610 height += f->extra_line_spacing;
1611 }
1612
1613 return height;
1614 }
1615
1616
1617
1618 static Lisp_Object
1619 string_from_display_spec (Lisp_Object spec)
1620 {
1621 if (VECTORP (spec))
1622 {
1623 for (ptrdiff_t i = 0; i < ASIZE (spec); i++)
1624 if (STRINGP (AREF (spec, i)))
1625 return AREF (spec, i);
1626 }
1627 else
1628 {
1629 for (; CONSP (spec); spec = XCDR (spec))
1630 if (STRINGP (XCAR (spec)))
1631 return XCAR (spec);
1632 }
1633 return spec;
1634 }
1635
1636
1637
1638
1639
1640 static int
1641 window_hscroll_limited (struct window *w, struct frame *f)
1642 {
1643 ptrdiff_t window_hscroll = w->hscroll;
1644 int window_text_width = window_box_width (w, TEXT_AREA);
1645 int colwidth = FRAME_COLUMN_WIDTH (f);
1646
1647 if (window_hscroll > (INT_MAX - window_text_width) / colwidth - 1)
1648 window_hscroll = (INT_MAX - window_text_width) / colwidth - 1;
1649
1650 return window_hscroll;
1651 }
1652
1653
1654
1655
1656
1657 static void
1658 reset_box_start_end_flags (struct it *it)
1659 {
1660
1661
1662 if (it->area == TEXT_AREA
1663
1664 && !(it->what == IT_IMAGE && it->image_id < 0))
1665 {
1666
1667
1668
1669
1670 if (it->face_box_p)
1671 it->start_of_box_run_p = false;
1672 it->end_of_box_run_p = false;
1673 }
1674 }
1675
1676
1677
1678
1679
1680
1681
1682 bool
1683 pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
1684 int *rtop, int *rbot, int *rowh, int *vpos)
1685 {
1686 struct it it;
1687 void *itdata = bidi_shelve_cache ();
1688 struct text_pos top;
1689 bool visible_p = false;
1690 struct buffer *old_buffer = NULL;
1691 bool r2l = false;
1692
1693 if (FRAME_INITIAL_P (XFRAME (WINDOW_FRAME (w))))
1694 return visible_p;
1695
1696 if (XBUFFER (w->contents) != current_buffer)
1697 {
1698 old_buffer = current_buffer;
1699 set_buffer_internal_1 (XBUFFER (w->contents));
1700 }
1701
1702 SET_TEXT_POS_FROM_MARKER (top, w->start);
1703
1704
1705
1706
1707 if (CHARPOS (top) > ZV || CHARPOS (top) < BEGV)
1708 SET_TEXT_POS (top, BEGV, BEGV_BYTE);
1709
1710
1711
1712 if (charpos >= 0 && CHARPOS (top) > charpos)
1713 return visible_p;
1714
1715
1716
1717
1718
1719
1720
1721
1722 int prev_mode_line_height = w->mode_line_height;
1723 int prev_header_line_height = w->header_line_height;
1724 int prev_tab_line_height = w->tab_line_height;
1725
1726 if (window_wants_mode_line (w))
1727 {
1728 Lisp_Object window_mode_line_format
1729 = window_parameter (w, Qmode_line_format);
1730
1731 w->mode_line_height
1732 = display_mode_line (w, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w),
1733 NILP (window_mode_line_format)
1734 ? BVAR (current_buffer, mode_line_format)
1735 : window_mode_line_format);
1736 }
1737
1738 if (window_wants_tab_line (w))
1739 {
1740 Lisp_Object window_tab_line_format
1741 = window_parameter (w, Qtab_line_format);
1742
1743 w->tab_line_height
1744 = display_mode_line (w, TAB_LINE_FACE_ID,
1745 NILP (window_tab_line_format)
1746 ? BVAR (current_buffer, tab_line_format)
1747 : window_tab_line_format);
1748 }
1749
1750 if (window_wants_header_line (w))
1751 {
1752 Lisp_Object window_header_line_format
1753 = window_parameter (w, Qheader_line_format);
1754
1755 w->header_line_height
1756 = display_mode_line (w, HEADER_LINE_FACE_ID,
1757 NILP (window_header_line_format)
1758 ? BVAR (current_buffer, header_line_format)
1759 : window_header_line_format);
1760 }
1761
1762 start_display (&it, w, top);
1763 move_it_to (&it, charpos, -1, it.last_visible_y - 1, -1,
1764 (charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y);
1765
1766
1767
1768 if (!NILP (Vdisplay_line_numbers)
1769 && it.current_x >= it.first_visible_x
1770 && IT_CHARPOS (it) == charpos
1771 && !it.line_number_produced_p)
1772 {
1773
1774
1775
1776 if (!it.lnum_pixel_width)
1777 {
1778 struct it it2;
1779 void *it2data = NULL;
1780
1781 SAVE_IT (it2, it, it2data);
1782 move_it_by_lines (&it, 1);
1783 it2.lnum_pixel_width = it.lnum_pixel_width;
1784 RESTORE_IT (&it, &it2, it2data);
1785 }
1786 it.current_x += it.lnum_pixel_width;
1787 }
1788
1789 if (charpos >= 0
1790 && (((!it.bidi_p || it.bidi_it.scan_dir != -1)
1791 && IT_CHARPOS (it) >= charpos)
1792
1793
1794
1795 || (it.bidi_p && it.bidi_it.scan_dir == -1
1796 && IT_CHARPOS (it) <= charpos)))
1797 {
1798
1799
1800
1801
1802
1803
1804 int top_x = it.current_x;
1805 int top_y = it.current_y;
1806 int window_top_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
1807 int bottom_y;
1808 struct it save_it;
1809 void *save_it_data = NULL;
1810
1811
1812 SAVE_IT (save_it, it, save_it_data);
1813 last_height = 0;
1814 bottom_y = line_bottom_y (&it);
1815 if (top_y < window_top_y)
1816 visible_p = bottom_y > window_top_y;
1817 else if (top_y < it.last_visible_y)
1818 visible_p = true;
1819 if (bottom_y >= it.last_visible_y
1820 && it.bidi_p && it.bidi_it.scan_dir == -1
1821 && IT_CHARPOS (it) < charpos)
1822 {
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833 int ten_more_lines = 10 * default_line_pixel_height (w);
1834
1835 move_it_to (&it, charpos, -1, bottom_y + ten_more_lines, -1,
1836 MOVE_TO_POS | MOVE_TO_Y);
1837 if (it.current_y > top_y)
1838 visible_p = false;
1839
1840 }
1841 RESTORE_IT (&it, &save_it, save_it_data);
1842 if (visible_p)
1843 {
1844 if (it.method == GET_FROM_DISPLAY_VECTOR)
1845 {
1846
1847
1848 if (charpos < 2 || top.charpos >= charpos)
1849 top_x = it.glyph_row->x;
1850 else
1851 {
1852 struct it it2, it2_prev;
1853
1854
1855
1856
1857
1858
1859 start_display (&it2, w, top);
1860 it2.glyph_row = NULL;
1861 move_it_to (&it2, charpos - 1, -1, -1, -1, MOVE_TO_POS);
1862
1863
1864
1865
1866 if (IT_CHARPOS (it2) != charpos - 1)
1867 it2_prev = it2;
1868 else
1869 {
1870
1871
1872
1873 do {
1874 get_next_display_element (&it2);
1875 PRODUCE_GLYPHS (&it2);
1876 it2_prev = it2;
1877 set_iterator_to_next (&it2, true);
1878 } while (it2.method == GET_FROM_DISPLAY_VECTOR
1879 && IT_CHARPOS (it2) < charpos);
1880 }
1881 if (ITERATOR_AT_END_OF_LINE_P (&it2_prev)
1882 || it2_prev.current_x > it2_prev.last_visible_x)
1883 top_x = it.glyph_row->x;
1884 else
1885 {
1886 top_x = it2_prev.current_x;
1887 top_y = it2_prev.current_y;
1888 }
1889 }
1890 }
1891 else if (IT_CHARPOS (it) != charpos)
1892 {
1893 Lisp_Object cpos = make_fixnum (charpos);
1894 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
1895 Lisp_Object string = string_from_display_spec (spec);
1896 struct text_pos tpos;
1897 bool newline_in_string
1898 = (STRINGP (string)
1899 && memchr (SDATA (string), '\n', SBYTES (string)));
1900
1901 SET_TEXT_POS (tpos, charpos, CHAR_TO_BYTE (charpos));
1902 bool replacing_spec_p
1903 = (!NILP (spec)
1904 && handle_display_spec (NULL, spec, Qnil, Qnil, &tpos,
1905 charpos, FRAME_WINDOW_P (it.f)));
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922 if (replacing_spec_p)
1923 {
1924 Lisp_Object startpos, endpos;
1925 EMACS_INT start, end;
1926 struct it it3;
1927
1928
1929
1930 endpos =
1931 Fnext_single_char_property_change (cpos, Qdisplay,
1932 Qnil, Qnil);
1933 startpos =
1934 Fprevious_single_char_property_change (endpos, Qdisplay,
1935 Qnil, Qnil);
1936 start = XFIXNAT (startpos);
1937 end = XFIXNAT (endpos);
1938
1939
1940 start_display (&it3, w, top);
1941 if (start > CHARPOS (top))
1942 move_it_to (&it3, start - 1, -1, -1, -1, MOVE_TO_POS);
1943
1944
1945
1946
1947 if (it3.method == GET_FROM_BUFFER
1948 && (it3.c == '\n'
1949 || FETCH_BYTE (IT_BYTEPOS (it3)) == '\n'))
1950 move_it_by_lines (&it3, 1);
1951 else if (move_it_in_display_line_to (&it3, -1,
1952 it3.current_x
1953 + it3.pixel_width,
1954 MOVE_TO_X)
1955 == MOVE_LINE_CONTINUED)
1956 {
1957 move_it_by_lines (&it3, 1);
1958
1959
1960
1961 if (it3.line_wrap == WORD_WRAP)
1962 move_it_by_lines (&it3, -1);
1963 }
1964
1965
1966
1967 top_y = it3.current_y;
1968 if (it3.bidi_p)
1969 {
1970
1971
1972
1973
1974
1975 start_display (&it3, w, top);
1976 move_it_to (&it3, end + 1, -1, -1, -1, MOVE_TO_POS);
1977 if (it3.current_y < top_y)
1978 top_y = it3.current_y;
1979 }
1980
1981
1982
1983 start_display (&it3, w, top);
1984 it3.glyph_row = NULL;
1985 move_it_to (&it3, -1, 0, top_y, -1, MOVE_TO_X | MOVE_TO_Y);
1986
1987
1988
1989
1990
1991
1992
1993 bool it3_moved = false;
1994 int top_x_before_string = it3.current_x;
1995
1996
1997
1998
1999
2000 while (get_next_display_element (&it3))
2001 {
2002 if (!EQ (it3.object, string))
2003 top_x_before_string = it3.current_x;
2004 PRODUCE_GLYPHS (&it3);
2005 if ((it3.bidi_it.scan_dir == 1
2006 && IT_CHARPOS (it3) >= charpos)
2007 || (it3.bidi_it.scan_dir == -1
2008 && IT_CHARPOS (it3) <= charpos)
2009 || ITERATOR_AT_END_OF_LINE_P (&it3))
2010 break;
2011 it3_moved = true;
2012 set_iterator_to_next (&it3, false);
2013 }
2014 top_x = it3.current_x - it3.pixel_width;
2015
2016
2017
2018 if (!it3.line_number_produced_p)
2019 {
2020 if (it3.lnum_pixel_width > 0)
2021 {
2022 top_x += it3.lnum_pixel_width;
2023 top_x_before_string += it3.lnum_pixel_width;
2024 }
2025 else if (it.line_number_produced_p)
2026 {
2027 top_x += it.lnum_pixel_width;
2028 top_x_before_string += it3.lnum_pixel_width;
2029 }
2030 }
2031
2032
2033
2034
2035
2036
2037 if (it3_moved
2038 && newline_in_string
2039 && IT_CHARPOS (it3) != charpos && EQ (it3.object, string))
2040 top_x = top_x_before_string;
2041 }
2042 }
2043
2044 *x = top_x;
2045
2046
2047
2048
2049 if (it.ascent == 0 && it.what == IT_IMAGE
2050 && it.method != GET_FROM_IMAGE
2051 && it.image_id < 0
2052 && it.max_ascent > 0)
2053 *y = max (top_y, window_top_y);
2054 else
2055 *y = max (top_y + max (0, it.max_ascent - it.ascent), window_top_y);
2056 *rtop = max (0, window_top_y - top_y);
2057 *rbot = max (0, bottom_y - it.last_visible_y);
2058 *rowh = max (0, (min (bottom_y, it.last_visible_y)
2059 - max (top_y, window_top_y)));
2060 *vpos = it.vpos;
2061 if (it.bidi_it.paragraph_dir == R2L)
2062 r2l = true;
2063 }
2064 }
2065 else
2066 {
2067
2068
2069
2070 struct it it2;
2071 void *it2data = NULL;
2072
2073 SAVE_IT (it2, it, it2data);
2074 if (IT_CHARPOS (it) < ZV && FETCH_BYTE (IT_BYTEPOS (it)) != '\n')
2075 move_it_by_lines (&it, 1);
2076 if (charpos < IT_CHARPOS (it)
2077 || (it.what == IT_EOB && charpos == IT_CHARPOS (it)))
2078 {
2079 visible_p = true;
2080 RESTORE_IT (&it2, &it2, it2data);
2081 move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS);
2082 *x = it2.current_x;
2083 if (it2.ascent == 0 && it2.what == IT_IMAGE
2084 && it2.method != GET_FROM_IMAGE
2085 && it2.image_id < 0
2086 && it2.max_ascent > 0)
2087 *y = it2.current_y;
2088 else
2089 *y = it2.current_y + it2.max_ascent - it2.ascent;
2090 *rtop = max (0, -it2.current_y);
2091 *rbot = max (0, ((it2.current_y + it2.max_ascent + it2.max_descent)
2092 - it.last_visible_y));
2093 *rowh = max (0, (min (it2.current_y + it2.max_ascent + it2.max_descent,
2094 it.last_visible_y)
2095 - max (max (it2.current_y,
2096 WINDOW_TAB_LINE_HEIGHT (w)),
2097 WINDOW_HEADER_LINE_HEIGHT (w))));
2098 *vpos = it2.vpos;
2099 if (it2.bidi_it.paragraph_dir == R2L)
2100 r2l = true;
2101 }
2102 else
2103 bidi_unshelve_cache (it2data, true);
2104 }
2105 bidi_unshelve_cache (itdata, false);
2106
2107 if (old_buffer)
2108 set_buffer_internal_1 (old_buffer);
2109
2110 if (visible_p)
2111 {
2112 if (w->hscroll > 0)
2113 *x -=
2114 window_hscroll_limited (w, WINDOW_XFRAME (w))
2115 * WINDOW_FRAME_COLUMN_WIDTH (w);
2116
2117
2118
2119
2120
2121 if (r2l)
2122 *x = window_box_width (w, TEXT_AREA) - *x - 1;
2123 }
2124
2125 #if false
2126
2127 if (visible_p)
2128 fprintf (stderr, "+pv pt=%d vs=%d --> x=%d y=%d rt=%d rb=%d rh=%d vp=%d\n",
2129 charpos, w->vscroll, *x, *y, *rtop, *rbot, *rowh, *vpos);
2130 else
2131 fprintf (stderr, "-pv pt=%d vs=%d\n", charpos, w->vscroll);
2132 #endif
2133
2134
2135 w->mode_line_height = prev_mode_line_height;
2136 w->header_line_height = prev_header_line_height;
2137 w->tab_line_height = prev_tab_line_height;
2138
2139 return visible_p;
2140 }
2141
2142
2143
2144
2145
2146
2147
2148 static int
2149 check_char_and_length (const unsigned char *str, int *len)
2150 {
2151 int c = string_char_and_length (str, len);
2152 if (!CHAR_VALID_P (c))
2153
2154
2155
2156 c = '?';
2157
2158 return c;
2159 }
2160
2161
2162
2163
2164
2165
2166 static struct text_pos
2167 string_pos_nchars_ahead (struct text_pos pos, Lisp_Object string, ptrdiff_t nchars)
2168 {
2169 eassert (STRINGP (string) && nchars >= 0);
2170
2171 if (STRING_MULTIBYTE (string))
2172 {
2173 const unsigned char *p = SDATA (string) + BYTEPOS (pos);
2174
2175 while (nchars--)
2176 {
2177 int len = BYTES_BY_CHAR_HEAD (*p);
2178 p += len;
2179 CHARPOS (pos) += 1;
2180 BYTEPOS (pos) += len;
2181 }
2182 }
2183 else
2184 SET_TEXT_POS (pos, CHARPOS (pos) + nchars, BYTEPOS (pos) + nchars);
2185
2186 return pos;
2187 }
2188
2189
2190
2191
2192
2193 static struct text_pos
2194 string_pos (ptrdiff_t charpos, Lisp_Object string)
2195 {
2196 struct text_pos pos;
2197 eassert (STRINGP (string));
2198 eassert (charpos >= 0);
2199 SET_TEXT_POS (pos, charpos, string_char_to_byte (string, charpos));
2200 return pos;
2201 }
2202
2203
2204
2205
2206
2207
2208 static struct text_pos
2209 c_string_pos (ptrdiff_t charpos, const char *s, bool multibyte_p)
2210 {
2211 struct text_pos pos;
2212
2213 eassert (s != NULL);
2214 eassert (charpos >= 0);
2215
2216 if (multibyte_p)
2217 {
2218 SET_TEXT_POS (pos, 0, 0);
2219 while (charpos--)
2220 {
2221 int len = BYTES_BY_CHAR_HEAD (*s);
2222 s += len;
2223 CHARPOS (pos) += 1;
2224 BYTEPOS (pos) += len;
2225 }
2226 }
2227 else
2228 SET_TEXT_POS (pos, charpos, charpos);
2229
2230 return pos;
2231 }
2232
2233
2234
2235
2236
2237 static ptrdiff_t
2238 number_of_chars (const char *s, bool multibyte_p)
2239 {
2240 ptrdiff_t nchars;
2241
2242 if (multibyte_p)
2243 {
2244 ptrdiff_t rest = strlen (s);
2245 const unsigned char *p = (const unsigned char *) s;
2246
2247 for (nchars = 0; rest > 0; ++nchars)
2248 {
2249 int len = BYTES_BY_CHAR_HEAD (*p);
2250 rest -= len, p += len;
2251 }
2252 }
2253 else
2254 nchars = strlen (s);
2255
2256 return nchars;
2257 }
2258
2259
2260
2261
2262
2263
2264 static void
2265 compute_string_pos (struct text_pos *newpos, struct text_pos pos, Lisp_Object string)
2266 {
2267 eassert (STRINGP (string));
2268 eassert (CHARPOS (*newpos) >= CHARPOS (pos));
2269
2270 if (STRING_MULTIBYTE (string))
2271 *newpos = string_pos_nchars_ahead (pos, string,
2272 CHARPOS (*newpos) - CHARPOS (pos));
2273 else
2274 BYTEPOS (*newpos) = CHARPOS (*newpos);
2275 }
2276
2277
2278
2279
2280
2281 int
2282 estimate_mode_line_height (struct frame *f, enum face_id face_id)
2283 {
2284 #ifdef HAVE_WINDOW_SYSTEM
2285 if (FRAME_WINDOW_P (f))
2286 {
2287 int height = FONT_HEIGHT (FRAME_FONT (f));
2288
2289
2290
2291 if (FRAME_FACE_CACHE (f))
2292 {
2293 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
2294 if (face)
2295 {
2296 if (face->font)
2297 height = normal_char_height (face->font, -1);
2298 if (face->box_horizontal_line_width > 0)
2299 height += 2 * face->box_horizontal_line_width;
2300 }
2301 }
2302
2303 return height;
2304 }
2305 #endif
2306
2307 return 1;
2308 }
2309
2310
2311
2312
2313
2314
2315 void
2316 pixel_to_glyph_coords (struct frame *f, int pix_x, int pix_y, int *x, int *y,
2317 NativeRectangle *bounds, bool noclip)
2318 {
2319
2320 #ifdef HAVE_WINDOW_SYSTEM
2321 if (FRAME_WINDOW_P (f))
2322 {
2323
2324
2325 if (pix_x < 0)
2326 pix_x -= FRAME_COLUMN_WIDTH (f) - 1;
2327 if (pix_y < 0)
2328 pix_y -= FRAME_LINE_HEIGHT (f) - 1;
2329
2330 pix_x = FRAME_PIXEL_X_TO_COL (f, pix_x);
2331 pix_y = FRAME_PIXEL_Y_TO_LINE (f, pix_y);
2332
2333 if (bounds)
2334 STORE_NATIVE_RECT (*bounds,
2335 FRAME_COL_TO_PIXEL_X (f, pix_x),
2336 FRAME_LINE_TO_PIXEL_Y (f, pix_y),
2337 FRAME_COLUMN_WIDTH (f) - 1,
2338 FRAME_LINE_HEIGHT (f) - 1);
2339
2340
2341 if (!noclip)
2342 {
2343 if (pix_x < 0)
2344 pix_x = 0;
2345 else if (pix_x > FRAME_TOTAL_COLS (f))
2346 pix_x = FRAME_TOTAL_COLS (f);
2347
2348 if (pix_y < 0)
2349 pix_y = 0;
2350 else if (pix_y > FRAME_TOTAL_LINES (f))
2351 pix_y = FRAME_TOTAL_LINES (f);
2352 }
2353 }
2354 #endif
2355
2356 *x = pix_x;
2357 *y = pix_y;
2358 }
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369 struct glyph *
2370 x_y_to_hpos_vpos (struct window *w, int x, int y, int *hpos, int *vpos,
2371 int *dx, int *dy, int *area)
2372 {
2373 struct glyph *glyph, *end;
2374 struct glyph_row *row = NULL;
2375 int x0, i;
2376
2377
2378 for (i = 0; i < w->current_matrix->nrows; ++i)
2379 {
2380 row = MATRIX_ROW (w->current_matrix, i);
2381 if (!row->enabled_p)
2382 return NULL;
2383 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
2384 break;
2385 }
2386
2387 *vpos = i;
2388 *hpos = 0;
2389
2390
2391 if (i == w->current_matrix->nrows)
2392 return NULL;
2393
2394
2395 if (w->pseudo_window_p)
2396 {
2397 *area = TEXT_AREA;
2398 x0 = 0;
2399 }
2400 else
2401 {
2402 if (x < window_box_left_offset (w, TEXT_AREA))
2403 {
2404 *area = LEFT_MARGIN_AREA;
2405 x0 = window_box_left_offset (w, LEFT_MARGIN_AREA);
2406 }
2407 else if (x < window_box_right_offset (w, TEXT_AREA))
2408 {
2409 *area = TEXT_AREA;
2410 x0 = window_box_left_offset (w, TEXT_AREA) + min (row->x, 0);
2411 }
2412 else
2413 {
2414 *area = RIGHT_MARGIN_AREA;
2415 x0 = window_box_left_offset (w, RIGHT_MARGIN_AREA);
2416 }
2417 }
2418
2419
2420 glyph = row->glyphs[*area];
2421 end = glyph + row->used[*area];
2422 x -= x0;
2423 while (glyph < end && x >= glyph->pixel_width)
2424 {
2425 x -= glyph->pixel_width;
2426 ++glyph;
2427 }
2428
2429 if (glyph == end)
2430 return NULL;
2431
2432 if (dx)
2433 {
2434 *dx = x;
2435 *dy = y - (row->y + row->ascent - glyph->ascent);
2436 }
2437
2438 *hpos = glyph - row->glyphs[*area];
2439 return glyph;
2440 }
2441
2442
2443
2444
2445 static void
2446 frame_to_window_pixel_xy (struct window *w, int *x, int *y)
2447 {
2448 if (w->pseudo_window_p)
2449 {
2450
2451
2452 struct frame *f = XFRAME (w->frame);
2453 *x -= FRAME_INTERNAL_BORDER_WIDTH (f);
2454 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
2455 }
2456 else
2457 {
2458 *x -= WINDOW_LEFT_EDGE_X (w);
2459 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
2460 }
2461 }
2462
2463 #ifdef HAVE_WINDOW_SYSTEM
2464
2465
2466
2467
2468
2469 int
2470 get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int n)
2471 {
2472 Emacs_Rectangle r;
2473
2474 if (n <= 0)
2475 return 0;
2476
2477 if (s->row->full_width_p)
2478 {
2479
2480 r.x = WINDOW_LEFT_EDGE_X (s->w);
2481 if (s->row->mode_line_p)
2482 r.width = WINDOW_PIXEL_WIDTH (s->w) - WINDOW_RIGHT_DIVIDER_WIDTH (s->w);
2483 else
2484 r.width = WINDOW_PIXEL_WIDTH (s->w);
2485
2486
2487
2488 if (s->w->pseudo_window_p)
2489 r.height = s->row->visible_height;
2490 else
2491 r.height = s->height;
2492 }
2493 else
2494 {
2495
2496 r.x = window_box_left (s->w, s->area);
2497 r.width = window_box_width (s->w, s->area);
2498 r.height = s->row->visible_height;
2499 }
2500
2501 if (s->clip_head)
2502 if (r.x < s->clip_head->x)
2503 {
2504 if (r.width >= s->clip_head->x - r.x)
2505 r.width -= s->clip_head->x - r.x;
2506 else
2507 r.width = 0;
2508 r.x = s->clip_head->x;
2509 }
2510 if (s->clip_tail)
2511 if (r.x + r.width > s->clip_tail->x + s->clip_tail->background_width)
2512 {
2513 if (s->clip_tail->x + s->clip_tail->background_width >= r.x)
2514 r.width = s->clip_tail->x + s->clip_tail->background_width - r.x;
2515 else
2516 r.width = 0;
2517 }
2518
2519
2520
2521
2522 if (s->for_overlaps)
2523 {
2524 r.y = WINDOW_TAB_LINE_HEIGHT (s->w) + WINDOW_HEADER_LINE_HEIGHT (s->w);
2525 r.height = window_text_bottom_y (s->w) - r.y;
2526
2527
2528
2529
2530
2531
2532 if (s->for_overlaps & OVERLAPS_ERASED_CURSOR)
2533 {
2534 Emacs_Rectangle rc, r_save = r;
2535
2536 rc.x = WINDOW_TEXT_TO_FRAME_PIXEL_X (s->w, s->w->phys_cursor.x);
2537 rc.y = s->w->phys_cursor.y;
2538 rc.width = s->w->phys_cursor_width;
2539 rc.height = s->w->phys_cursor_height;
2540
2541 gui_intersect_rectangles (&r_save, &rc, &r);
2542 }
2543 }
2544 else
2545 {
2546
2547
2548
2549 if (!s->row->full_width_p
2550 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2551 r.y = WINDOW_TAB_LINE_HEIGHT (s->w) + WINDOW_HEADER_LINE_HEIGHT (s->w);
2552 else
2553 r.y = max (0, s->row->y);
2554 }
2555
2556 r.y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r.y);
2557
2558
2559
2560 if (s->hl == DRAW_CURSOR)
2561 {
2562 struct glyph *glyph = s->first_glyph;
2563 int height, max_y;
2564
2565 if (s->x > r.x)
2566 {
2567 if (r.width >= s->x - r.x)
2568 r.width -= s->x - r.x;
2569 else
2570 r.width = 0;
2571 r.x = s->x;
2572 }
2573 r.width = min (r.width, glyph->pixel_width);
2574
2575
2576 height = min (glyph->ascent + glyph->descent,
2577 min (FRAME_LINE_HEIGHT (s->f), s->row->visible_height));
2578 max_y = window_text_bottom_y (s->w) - height;
2579 max_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, max_y);
2580 if (s->ybase - glyph->ascent > max_y)
2581 {
2582 r.y = max_y;
2583 r.height = height;
2584 }
2585 else
2586 {
2587
2588 height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent);
2589 if (height < r.height)
2590 {
2591 max_y = r.y + r.height;
2592 r.y = min (max_y, max (r.y, s->ybase + glyph->descent - height));
2593 r.height = min (max_y - r.y, height);
2594 }
2595 }
2596 }
2597
2598 if (s->row->clip)
2599 {
2600 Emacs_Rectangle r_save = r;
2601
2602 if (! gui_intersect_rectangles (&r_save, s->row->clip, &r))
2603 r.width = 0;
2604 }
2605
2606 if ((s->for_overlaps & OVERLAPS_BOTH) == 0
2607 || ((s->for_overlaps & OVERLAPS_BOTH) == OVERLAPS_BOTH && n == 1))
2608 {
2609 #ifdef CONVERT_FROM_EMACS_RECT
2610 CONVERT_FROM_EMACS_RECT (r, *rects);
2611 #else
2612 *rects = r;
2613 #endif
2614 return 1;
2615 }
2616 else
2617 {
2618
2619
2620
2621
2622 #ifdef CONVERT_FROM_EMACS_RECT
2623 Emacs_Rectangle rs[2];
2624 #else
2625 Emacs_Rectangle *rs = rects;
2626 #endif
2627 int i = 0, row_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, s->row->y);
2628
2629 if (s->for_overlaps & OVERLAPS_PRED)
2630 {
2631 rs[i] = r;
2632 if (r.y + r.height > row_y)
2633 {
2634 if (r.y < row_y)
2635 rs[i].height = row_y - r.y;
2636 else
2637 rs[i].height = 0;
2638 }
2639 i++;
2640 }
2641 if (s->for_overlaps & OVERLAPS_SUCC)
2642 {
2643 rs[i] = r;
2644 if (r.y < row_y + s->row->visible_height)
2645 {
2646 if (r.y + r.height > row_y + s->row->visible_height)
2647 {
2648 rs[i].y = row_y + s->row->visible_height;
2649 rs[i].height = r.y + r.height - rs[i].y;
2650 }
2651 else
2652 rs[i].height = 0;
2653 }
2654 i++;
2655 }
2656
2657 n = i;
2658 #ifdef CONVERT_FROM_EMACS_RECT
2659 for (i = 0; i < n; i++)
2660 CONVERT_FROM_EMACS_RECT (rs[i], rects[i]);
2661 #endif
2662 return n;
2663 }
2664 }
2665
2666
2667
2668
2669 void
2670 get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr)
2671 {
2672 get_glyph_string_clip_rects (s, nr, 1);
2673 }
2674
2675
2676
2677
2678
2679
2680
2681 void
2682 get_phys_cursor_geometry (struct window *w, struct glyph_row *row,
2683 struct glyph *glyph, int *xp, int *yp, int *heightp)
2684 {
2685 struct frame *f = XFRAME (WINDOW_FRAME (w));
2686 int x, y, wd, h, h0, y0, ascent;
2687
2688
2689
2690
2691
2692 wd = glyph->pixel_width;
2693
2694 x = w->phys_cursor.x;
2695 if (x < 0)
2696 {
2697 wd += x;
2698 x = 0;
2699 }
2700
2701 if (glyph->type == STRETCH_GLYPH
2702 && !x_stretch_cursor_p)
2703 wd = min (FRAME_COLUMN_WIDTH (f), wd);
2704 w->phys_cursor_width = wd;
2705
2706
2707
2708 y = w->phys_cursor.y;
2709 ascent = row->ascent;
2710
2711
2712
2713 if (!row->ends_at_zv_p && row->ascent < glyph->ascent)
2714 {
2715 y -= glyph->ascent - row->ascent;
2716 ascent = glyph->ascent;
2717 }
2718
2719
2720 h0 = min (FRAME_LINE_HEIGHT (f), row->visible_height);
2721
2722 h = max (h0, ascent + glyph->descent);
2723
2724
2725 h = min (h, row->height);
2726 h0 = min (h0, ascent + glyph->descent);
2727
2728 y0 = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
2729 if (y < y0)
2730 {
2731 h = max (h - (y0 - y) + 1, h0);
2732 y = y0 - 1;
2733 }
2734 else
2735 {
2736 y0 = window_text_bottom_y (w) - h0;
2737 if (y > y0)
2738 {
2739 h += y - y0;
2740 y = y0;
2741 }
2742 }
2743
2744 *xp = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
2745 *yp = WINDOW_TO_FRAME_PIXEL_Y (w, y);
2746 *heightp = h;
2747 }
2748
2749
2750
2751
2752
2753 void
2754 remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
2755 {
2756 Lisp_Object window;
2757 struct window *w;
2758 struct glyph_row *r, *gr, *end_row;
2759 enum window_part part;
2760 enum glyph_row_area area;
2761 int x, y, width, height;
2762
2763 if (mouse_fine_grained_tracking)
2764 {
2765 STORE_NATIVE_RECT (*rect, gx, gy, 1, 1);
2766 return;
2767 }
2768
2769
2770
2771
2772 if (window_resize_pixelwise)
2773 {
2774 width = height = 1;
2775 goto virtual_glyph;
2776 }
2777 else if (!f->glyphs_initialized_p
2778 || (window = window_from_coordinates (f, gx, gy, &part, false, false),
2779 NILP (window)))
2780 {
2781 width = FRAME_SMALLEST_CHAR_WIDTH (f);
2782 height = FRAME_SMALLEST_FONT_HEIGHT (f);
2783 goto virtual_glyph;
2784 }
2785
2786 w = XWINDOW (window);
2787 width = WINDOW_FRAME_COLUMN_WIDTH (w);
2788 height = WINDOW_FRAME_LINE_HEIGHT (w);
2789
2790 x = window_relative_x_coord (w, part, gx);
2791 y = gy - WINDOW_TOP_EDGE_Y (w);
2792
2793 r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
2794 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
2795
2796 if (w->pseudo_window_p)
2797 {
2798 area = TEXT_AREA;
2799 part = ON_MODE_LINE;
2800 goto text_glyph;
2801 }
2802
2803 switch (part)
2804 {
2805 case ON_LEFT_MARGIN:
2806 area = LEFT_MARGIN_AREA;
2807 goto text_glyph;
2808
2809 case ON_RIGHT_MARGIN:
2810 area = RIGHT_MARGIN_AREA;
2811 goto text_glyph;
2812
2813 case ON_TAB_LINE:
2814 case ON_HEADER_LINE:
2815 case ON_MODE_LINE:
2816 gr = (part == ON_TAB_LINE
2817 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
2818 : (part == ON_HEADER_LINE
2819 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
2820 : MATRIX_MODE_LINE_ROW (w->current_matrix)));
2821 gy = gr->y;
2822 area = TEXT_AREA;
2823 goto text_glyph_row_found;
2824
2825 case ON_TEXT:
2826 area = TEXT_AREA;
2827
2828 text_glyph:
2829 gr = 0; gy = 0;
2830 for (; r <= end_row && r->enabled_p; ++r)
2831 if (r->y + r->height > y)
2832 {
2833 gr = r; gy = r->y;
2834 break;
2835 }
2836
2837 text_glyph_row_found:
2838 if (gr && gy <= y)
2839 {
2840 struct glyph *g = gr->glyphs[area];
2841 struct glyph *end = g + gr->used[area];
2842
2843 height = gr->height;
2844 for (gx = gr->x; g < end; gx += g->pixel_width, ++g)
2845 if (gx + g->pixel_width > x)
2846 break;
2847
2848 if (g < end)
2849 {
2850 if (g->type == IMAGE_GLYPH)
2851 {
2852
2853
2854 STORE_NATIVE_RECT (*rect, 0, 0, 0, 0);
2855 return;
2856 }
2857 width = g->pixel_width;
2858 }
2859 else
2860 {
2861
2862 x -= gx;
2863 gx += (x / width) * width;
2864 }
2865
2866 if (part != ON_MODE_LINE && part != ON_HEADER_LINE
2867 && part != ON_TAB_LINE)
2868 {
2869 gx += window_box_left_offset (w, area);
2870
2871
2872 height = min (height,
2873 max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
2874 }
2875 }
2876 else
2877 {
2878
2879 gx = (x / width) * width;
2880 y -= gy;
2881 gy += (y / height) * height;
2882 if (part != ON_MODE_LINE && part != ON_HEADER_LINE
2883 && part != ON_TAB_LINE)
2884
2885 height = min (height,
2886 max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
2887 }
2888 break;
2889
2890 case ON_LEFT_FRINGE:
2891 gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2892 ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w)
2893 : window_box_right_offset (w, LEFT_MARGIN_AREA));
2894 width = WINDOW_LEFT_FRINGE_WIDTH (w);
2895 goto row_glyph;
2896
2897 case ON_RIGHT_FRINGE:
2898 gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2899 ? window_box_right_offset (w, RIGHT_MARGIN_AREA)
2900 : window_box_right_offset (w, TEXT_AREA));
2901 if (WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
2902 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
2903 && !WINDOW_RIGHTMOST_P (w))
2904 if (gx < WINDOW_PIXEL_WIDTH (w) - width)
2905
2906
2907 width = WINDOW_RIGHT_FRINGE_WIDTH (w) - width;
2908 else
2909 width = WINDOW_PIXEL_WIDTH (w) - gx;
2910 else
2911 width = WINDOW_RIGHT_FRINGE_WIDTH (w);
2912
2913 goto row_glyph;
2914
2915 case ON_VERTICAL_BORDER:
2916 gx = WINDOW_PIXEL_WIDTH (w) - width;
2917 goto row_glyph;
2918
2919 case ON_VERTICAL_SCROLL_BAR:
2920 gx = (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
2921 ? 0
2922 : (window_box_right_offset (w, RIGHT_MARGIN_AREA)
2923 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2924 ? WINDOW_RIGHT_FRINGE_WIDTH (w)
2925 : 0)));
2926 width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
2927
2928 row_glyph:
2929 gr = 0, gy = 0;
2930 for (; r <= end_row && r->enabled_p; ++r)
2931 if (r->y + r->height > y)
2932 {
2933 gr = r; gy = r->y;
2934 break;
2935 }
2936
2937 if (gr && gy <= y)
2938 height = gr->height;
2939 else
2940 {
2941
2942 y -= gy;
2943 gy += (y / height) * height;
2944 }
2945 break;
2946
2947 case ON_RIGHT_DIVIDER:
2948 gx = WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
2949 width = WINDOW_RIGHT_DIVIDER_WIDTH (w);
2950 gy = 0;
2951
2952 height = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2953 goto add_edge;
2954
2955 case ON_BOTTOM_DIVIDER:
2956 gx = 0;
2957 width = WINDOW_PIXEL_WIDTH (w);
2958 gy = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2959 height = WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2960 goto add_edge;
2961
2962 default:
2963 ;
2964 virtual_glyph:
2965
2966
2967
2968
2969
2970
2971 if (gx < 0)
2972 gx -= width - 1;
2973 if (gy < 0)
2974 gy -= height - 1;
2975
2976 gx = (gx / width) * width;
2977 gy = (gy / height) * height;
2978
2979 goto store_rect;
2980 }
2981
2982 add_edge:
2983 gx += WINDOW_LEFT_EDGE_X (w);
2984 gy += WINDOW_TOP_EDGE_Y (w);
2985
2986 store_rect:
2987 STORE_NATIVE_RECT (*rect, gx, gy, width, height);
2988
2989
2990 #if false && defined HAVE_X_WINDOWS
2991 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
2992 f->output_data.x->normal_gc,
2993 gx, gy, width, height);
2994 #endif
2995 }
2996
2997
2998 #endif
2999
3000 static void
3001 adjust_window_ends (struct window *w, struct glyph_row *row, bool current)
3002 {
3003 eassert (w);
3004 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
3005 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
3006 w->window_end_vpos
3007 = MATRIX_ROW_VPOS (row, current ? w->current_matrix : w->desired_matrix);
3008 }
3009
3010 static bool
3011 hscrolling_current_line_p (struct window *w)
3012 {
3013 return (!w->suspend_auto_hscroll
3014 && EQ (Fbuffer_local_value (Qauto_hscroll_mode, w->contents),
3015 Qcurrent_line));
3016 }
3017
3018
3019
3020
3021
3022
3023
3024 static Lisp_Object
3025 safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
3026 {
3027 add_to_log ("Error during redisplay: %S signaled %S",
3028 Flist (nargs, args), arg);
3029 return Qnil;
3030 }
3031
3032
3033
3034
3035
3036 static Lisp_Object
3037 safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
3038 {
3039 Lisp_Object val;
3040
3041 if (inhibit_eval_during_redisplay)
3042 val = Qnil;
3043 else
3044 {
3045 ptrdiff_t i;
3046 specpdl_ref count = SPECPDL_INDEX ();
3047 Lisp_Object *args;
3048 USE_SAFE_ALLOCA;
3049 SAFE_ALLOCA_LISP (args, nargs);
3050
3051 args[0] = func;
3052 for (i = 1; i < nargs; i++)
3053 args[i] = va_arg (ap, Lisp_Object);
3054
3055 specbind (Qinhibit_redisplay, Qt);
3056 if (inhibit_quit)
3057 specbind (Qinhibit_quit, Qt);
3058
3059
3060 val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
3061 safe_eval_handler);
3062 val = SAFE_FREE_UNBIND_TO (count, val);
3063 }
3064
3065 return val;
3066 }
3067
3068 Lisp_Object
3069 safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
3070 {
3071 Lisp_Object retval;
3072 va_list ap;
3073
3074 va_start (ap, func);
3075 retval = safe__call (false, nargs, func, ap);
3076 va_end (ap);
3077 return retval;
3078 }
3079
3080
3081
3082
3083 Lisp_Object
3084 safe_call1 (Lisp_Object fn, Lisp_Object arg)
3085 {
3086 return safe_call (2, fn, arg);
3087 }
3088
3089 static Lisp_Object
3090 safe__call1 (bool inhibit_quit, Lisp_Object fn, ...)
3091 {
3092 Lisp_Object retval;
3093 va_list ap;
3094
3095 va_start (ap, fn);
3096 retval = safe__call (inhibit_quit, 2, fn, ap);
3097 va_end (ap);
3098 return retval;
3099 }
3100
3101 Lisp_Object
3102 safe_eval (Lisp_Object sexpr)
3103 {
3104 return safe__call1 (false, Qeval, sexpr);
3105 }
3106
3107 static Lisp_Object
3108 safe__eval (bool inhibit_quit, Lisp_Object sexpr)
3109 {
3110 return safe__call1 (inhibit_quit, Qeval, sexpr);
3111 }
3112
3113
3114
3115
3116 Lisp_Object
3117 safe_call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2)
3118 {
3119 return safe_call (3, fn, arg1, arg2);
3120 }
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131 static void
3132 CHECK_IT (struct it *it)
3133 {
3134 #if false
3135 if (it->method == GET_FROM_STRING)
3136 {
3137 eassert (STRINGP (it->string));
3138 eassert (IT_STRING_CHARPOS (*it) >= 0);
3139 }
3140 else
3141 {
3142 eassert (IT_STRING_CHARPOS (*it) < 0);
3143 if (it->method == GET_FROM_BUFFER)
3144 {
3145
3146 eassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
3147 }
3148 }
3149
3150 if (it->dpvec)
3151 eassert (it->current.dpvec_index >= 0);
3152 else
3153 eassert (it->current.dpvec_index < 0);
3154 #endif
3155 }
3156
3157
3158
3159
3160
3161 static void
3162 CHECK_WINDOW_END (struct window *w)
3163 {
3164 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
3165 if (!MINI_WINDOW_P (w) && w->window_end_valid)
3166 {
3167 struct glyph_row *row;
3168 eassert ((row = MATRIX_ROW (w->current_matrix, w->window_end_vpos),
3169 !row->enabled_p
3170 || MATRIX_ROW_DISPLAYS_TEXT_P (row)
3171 || MATRIX_ROW_VPOS (row, w->current_matrix) == 0));
3172 }
3173 #endif
3174 }
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199 void
3200 init_iterator (struct it *it, struct window *w,
3201 ptrdiff_t charpos, ptrdiff_t bytepos,
3202 struct glyph_row *row, enum face_id base_face_id)
3203 {
3204 enum face_id remapped_base_face_id = base_face_id;
3205 int body_width = 0, body_height = 0;
3206
3207
3208 eassert (w != NULL && it != NULL);
3209 eassert (charpos < 0 || (charpos >= BUF_BEG (current_buffer)
3210 && charpos <= ZV));
3211
3212
3213
3214
3215
3216 if (!inhibit_free_realized_faces)
3217 {
3218 if (face_change)
3219 {
3220 face_change = false;
3221 XFRAME (w->frame)->face_change = 0;
3222 free_all_realized_faces (Qnil);
3223 }
3224 else if (XFRAME (w->frame)->face_change)
3225 {
3226 XFRAME (w->frame)->face_change = 0;
3227 free_all_realized_faces (w->frame);
3228 }
3229 }
3230
3231
3232 if (! NILP (Vface_remapping_alist))
3233 remapped_base_face_id
3234 = lookup_basic_face (w, XFRAME (w->frame), base_face_id);
3235
3236
3237
3238 if (row == NULL)
3239 {
3240 if (base_face_id == MODE_LINE_ACTIVE_FACE_ID
3241 || base_face_id == MODE_LINE_INACTIVE_FACE_ID)
3242 row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
3243 else if (base_face_id == TAB_LINE_FACE_ID)
3244 row = MATRIX_TAB_LINE_ROW (w->desired_matrix);
3245 else if (base_face_id == HEADER_LINE_FACE_ID)
3246 {
3247
3248 w->desired_matrix->tab_line_p = window_wants_tab_line (w);
3249 row = MATRIX_HEADER_LINE_ROW (w->desired_matrix);
3250 }
3251 }
3252
3253
3254
3255 memclear (it, sizeof *it);
3256 it->current.overlay_string_index = -1;
3257 it->current.dpvec_index = -1;
3258 it->base_face_id = remapped_base_face_id;
3259 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
3260 it->paragraph_embedding = L2R;
3261 it->bidi_it.w = w;
3262
3263
3264 XSETWINDOW (it->window, w);
3265 it->w = w;
3266 it->f = XFRAME (w->frame);
3267
3268 it->cmp_it.id = -1;
3269 it->cmp_it.parent_it = it;
3270
3271 if (max_redisplay_ticks > 0)
3272 update_redisplay_ticks (0, w);
3273
3274
3275 if (base_face_id == DEFAULT_FACE_ID
3276 && FRAME_WINDOW_P (it->f))
3277 {
3278 if (FIXNATP (BVAR (current_buffer, extra_line_spacing)))
3279 it->extra_line_spacing = XFIXNAT (BVAR (current_buffer, extra_line_spacing));
3280 else if (FLOATP (BVAR (current_buffer, extra_line_spacing)))
3281 it->extra_line_spacing = (XFLOAT_DATA (BVAR (current_buffer, extra_line_spacing))
3282 * FRAME_LINE_HEIGHT (it->f));
3283 else if (it->f->extra_line_spacing > 0)
3284 it->extra_line_spacing = it->f->extra_line_spacing;
3285 }
3286
3287
3288
3289
3290
3291 if (FRAME_FACE_CACHE (it->f) == NULL)
3292 init_frame_faces (it->f);
3293 if (FRAME_FACE_CACHE (it->f)->used == 0)
3294 recompute_basic_faces (it->f);
3295
3296 it->override_ascent = -1;
3297
3298
3299 it->ctl_arrow_p = !NILP (BVAR (current_buffer, ctl_arrow));
3300
3301
3302
3303
3304 it->selective = (FIXNUMP (BVAR (current_buffer, selective_display))
3305 ? (clip_to_bounds
3306 (-1, XFIXNUM (BVAR (current_buffer, selective_display)),
3307 PTRDIFF_MAX))
3308 : (!NILP (BVAR (current_buffer, selective_display))
3309 ? -1 : 0));
3310 it->selective_display_ellipsis_p
3311 = !NILP (BVAR (current_buffer, selective_display_ellipses));
3312
3313
3314 it->dp = window_display_table (w);
3315
3316
3317 it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
3318
3319 it->tab_width = SANE_TAB_WIDTH (current_buffer);
3320
3321
3322 if (TRUNCATE != 0)
3323 it->line_wrap = TRUNCATE;
3324 if (base_face_id == DEFAULT_FACE_ID
3325 && !it->w->hscroll
3326 && (WINDOW_FULL_WIDTH_P (it->w)
3327 || NILP (Vtruncate_partial_width_windows)
3328 || (FIXNUMP (Vtruncate_partial_width_windows)
3329
3330 && (XFIXNUM (Vtruncate_partial_width_windows)
3331 <= WINDOW_TOTAL_COLS (it->w))))
3332 && NILP (BVAR (current_buffer, truncate_lines)))
3333 it->line_wrap = NILP (BVAR (current_buffer, word_wrap))
3334 ? WINDOW_WRAP : WORD_WRAP;
3335
3336
3337
3338
3339
3340
3341
3342 #ifdef HAVE_WINDOW_SYSTEM
3343 if (!(FRAME_WINDOW_P (it->f) && it->f->no_special_glyphs))
3344 #endif
3345 {
3346 if (it->line_wrap == TRUNCATE)
3347 {
3348
3349 eassert (it->glyph_row == NULL);
3350 produce_special_glyphs (it, IT_TRUNCATION);
3351 it->truncation_pixel_width = it->pixel_width;
3352 }
3353 else
3354 {
3355
3356 eassert (it->glyph_row == NULL);
3357 produce_special_glyphs (it, IT_CONTINUATION);
3358 it->continuation_pixel_width = it->pixel_width;
3359 }
3360 }
3361
3362
3363
3364 it->pixel_width = it->ascent = it->descent = 0;
3365 it->phys_ascent = it->phys_descent = 0;
3366
3367
3368
3369
3370 it->glyph_row = row;
3371 it->area = TEXT_AREA;
3372
3373
3374
3375
3376
3377 if (base_face_id != DEFAULT_FACE_ID)
3378 {
3379
3380 it->first_visible_x = 0;
3381 it->last_visible_x =
3382 WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
3383 }
3384 else
3385 {
3386
3387
3388
3389
3390
3391
3392 if (hscrolling_current_line_p (w))
3393 {
3394 if (w->min_hscroll > 0)
3395 it->first_visible_x = w->min_hscroll * FRAME_COLUMN_WIDTH (it->f);
3396 else
3397 it->first_visible_x = 0;
3398 }
3399 else
3400 it->first_visible_x =
3401 window_hscroll_limited (w, it->f) * FRAME_COLUMN_WIDTH (it->f);
3402
3403 body_width = window_box_width (w, TEXT_AREA);
3404 if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
3405 && body_width != w->old_body_pixel_width)
3406 FRAME_WINDOW_CHANGE (it->f) = true;
3407 it->last_visible_x = it->first_visible_x + body_width;
3408
3409
3410
3411
3412 if (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)
3413 {
3414 if (it->line_wrap == TRUNCATE)
3415 it->last_visible_x -= it->truncation_pixel_width;
3416 else
3417 it->last_visible_x -= it->continuation_pixel_width;
3418 }
3419
3420 it->tab_line_p = window_wants_tab_line (w);
3421 it->header_line_p = window_wants_header_line (w);
3422 body_height = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
3423 it->current_y = body_height + w->vscroll;
3424 }
3425
3426
3427 if (!FRAME_WINDOW_P (it->f)
3428 && !WINDOW_RIGHTMOST_P (it->w))
3429 it->last_visible_x -= 1;
3430
3431 it->last_visible_y = window_text_bottom_y (w);
3432 body_height += it->last_visible_y;
3433 if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
3434 && body_height != w->old_body_pixel_height)
3435 FRAME_WINDOW_CHANGE (it->f) = true;
3436
3437
3438
3439 if (base_face_id != DEFAULT_FACE_ID)
3440 {
3441 struct face *face;
3442
3443 it->face_id = remapped_base_face_id;
3444
3445
3446
3447 face = FACE_FROM_ID_OR_NULL (it->f, remapped_base_face_id);
3448 if (face && face->box != FACE_NO_BOX)
3449 {
3450 int box_thickness = face->box_vertical_line_width;
3451 it->face_box_p = true;
3452 it->start_of_box_run_p = true;
3453
3454
3455 if (box_thickness > 0)
3456 it->last_visible_x -= box_thickness;
3457 }
3458 }
3459
3460
3461
3462 if (charpos >= BUF_BEG (current_buffer))
3463 {
3464 it->stop_charpos = charpos;
3465 it->end_charpos = ZV;
3466 eassert (charpos == BYTE_TO_CHAR (bytepos));
3467 IT_CHARPOS (*it) = charpos;
3468 IT_BYTEPOS (*it) = bytepos;
3469
3470
3471
3472 it->face_id = it->base_face_id;
3473
3474 it->start = it->current;
3475
3476
3477
3478
3479
3480
3481
3482 it->bidi_p =
3483 !redisplay__inhibit_bidi
3484 && !NILP (BVAR (current_buffer, bidi_display_reordering))
3485 && it->multibyte_p;
3486
3487
3488
3489 if (it->bidi_p)
3490 {
3491
3492
3493
3494
3495 if (base_face_id == DEFAULT_FACE_ID
3496 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
3497 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) != 0)
3498 {
3499 if (it->line_wrap == TRUNCATE)
3500 it->last_visible_x -= it->truncation_pixel_width;
3501 else
3502 it->last_visible_x -= it->continuation_pixel_width;
3503 }
3504
3505
3506 if (EQ (BVAR (current_buffer, bidi_paragraph_direction),
3507 Qleft_to_right))
3508 it->paragraph_embedding = L2R;
3509 else if (EQ (BVAR (current_buffer, bidi_paragraph_direction),
3510 Qright_to_left))
3511 it->paragraph_embedding = R2L;
3512 else
3513 it->paragraph_embedding = NEUTRAL_DIR;
3514 bidi_unshelve_cache (NULL, false);
3515 bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
3516 &it->bidi_it);
3517 }
3518
3519
3520
3521 it->medium_narrowing_begv = 0;
3522
3523
3524 reseat (it, it->current.pos, true);
3525 }
3526
3527 CHECK_IT (it);
3528 }
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616 static int
3617 get_narrowed_width (struct window *w)
3618 {
3619
3620
3621 int fact = FRAME_WINDOW_P (XFRAME (w->frame)) ? 3 : 2;
3622
3623
3624
3625 int width = window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS)
3626 - ((WINDOW_RIGHT_FRINGE_WIDTH (w) == 0
3627 || WINDOW_LEFT_FRINGE_WIDTH (w) == 0) ? 1 : 0);
3628 return fact * max (1, width);
3629 }
3630
3631 static int
3632 get_narrowed_len (struct window *w)
3633 {
3634 int height = window_body_height (w, WINDOW_BODY_IN_CANONICAL_CHARS);
3635 return get_narrowed_width (w) * max (1, height);
3636 }
3637
3638 static ptrdiff_t
3639 get_medium_narrowing_begv (struct window *w, ptrdiff_t pos)
3640 {
3641 int len = get_narrowed_len (w);
3642 return max ((pos / len - 1) * len, BEGV);
3643 }
3644
3645 static ptrdiff_t
3646 get_medium_narrowing_zv (struct window *w, ptrdiff_t pos)
3647 {
3648 int len = get_narrowed_len (w);
3649 return min ((pos / len + 1) * len, ZV);
3650 }
3651
3652
3653
3654
3655
3656
3657 static ptrdiff_t
3658 get_nearby_bol_pos (ptrdiff_t pos)
3659 {
3660 ptrdiff_t start, pos_bytepos, cur, next, found, bol = BEGV - 1, init_pos = pos;
3661 int dist;
3662 for (dist = 500; dist <= 500000; dist *= 10)
3663 {
3664 pos_bytepos = pos == BEGV ? BEGV_BYTE : CHAR_TO_BYTE (pos);
3665 start = pos - dist < BEGV ? BEGV : pos - dist;
3666 for (cur = start; cur < pos; cur = next)
3667 {
3668 next = find_newline1 (cur, CHAR_TO_BYTE (cur),
3669 pos, pos_bytepos,
3670 1, &found, NULL, false);
3671 if (found)
3672 bol = next;
3673 else
3674 break;
3675 }
3676 if (bol >= BEGV || start == BEGV)
3677 break;
3678 else
3679 pos = pos - dist < BEGV ? BEGV : pos - dist;
3680 }
3681 eassert (bol <= init_pos);
3682 return bol;
3683 }
3684
3685 ptrdiff_t
3686 get_small_narrowing_begv (struct window *w, ptrdiff_t pos)
3687 {
3688 int len = get_narrowed_width (w);
3689 ptrdiff_t bol_pos = max (get_nearby_bol_pos (pos), BEGV);
3690 return max (bol_pos + ((pos - bol_pos) / len - 1) * len, BEGV);
3691 }
3692
3693 ptrdiff_t
3694 get_large_narrowing_begv (ptrdiff_t pos)
3695 {
3696 if (long_line_optimizations_region_size <= 0)
3697 return BEGV;
3698 int len = long_line_optimizations_region_size / 2;
3699 int begv = max (pos - len, BEGV);
3700 int limit = long_line_optimizations_bol_search_limit;
3701 while (limit > 0)
3702 {
3703 if (begv == BEGV || FETCH_BYTE (CHAR_TO_BYTE (begv) - 1) == '\n')
3704 return begv;
3705 begv--;
3706 limit--;
3707 }
3708 return begv;
3709 }
3710
3711 ptrdiff_t
3712 get_large_narrowing_zv (ptrdiff_t pos)
3713 {
3714 if (long_line_optimizations_region_size <= 0)
3715 return ZV;
3716 int len = long_line_optimizations_region_size / 2;
3717 return min (pos + len, ZV);
3718 }
3719
3720 static void
3721 unwind_narrowed_begv (Lisp_Object point_min)
3722 {
3723 SET_BUF_BEGV (current_buffer, XFIXNUM (point_min));
3724 }
3725
3726
3727
3728
3729 #define SET_WITH_NARROWED_BEGV(IT,DST,EXPR,BV) \
3730 do { \
3731 if (IT->medium_narrowing_begv) \
3732 { \
3733 specpdl_ref count = SPECPDL_INDEX (); \
3734 record_unwind_protect (unwind_narrowed_begv, Fpoint_min ()); \
3735 SET_BUF_BEGV (current_buffer, BV); \
3736 DST = EXPR; \
3737 unbind_to (count, Qnil); \
3738 } \
3739 else \
3740 DST = EXPR; \
3741 } while (0)
3742
3743
3744
3745 void
3746 start_display (struct it *it, struct window *w, struct text_pos pos)
3747 {
3748 struct glyph_row *row;
3749 int first_vpos = window_wants_tab_line (w) + window_wants_header_line (w);
3750
3751 row = w->desired_matrix->rows + first_vpos;
3752 init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
3753 it->first_vpos = first_vpos;
3754
3755
3756
3757 if (it->method == GET_FROM_BUFFER && it->line_wrap != TRUNCATE)
3758 {
3759 int first_y = it->current_y;
3760
3761
3762
3763 bool start_at_line_beg_p = (CHARPOS (pos) == BEGV
3764 || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n');
3765 if (!start_at_line_beg_p)
3766 {
3767 int new_x;
3768
3769 reseat_at_previous_visible_line_start (it);
3770 move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS);
3771
3772 new_x = it->current_x + it->pixel_width;
3773
3774
3775
3776
3777
3778
3779
3780 if (it->current_x > 0
3781 && it->line_wrap != TRUNCATE
3782 && (
3783 new_x > it->last_visible_x
3784
3785
3786 || (new_x == it->last_visible_x
3787 && FRAME_WINDOW_P (it->f)
3788 && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
3789 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
3790 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
3791 {
3792 if ((it->current.dpvec_index >= 0
3793 || it->current.overlay_string_index >= 0)
3794
3795
3796
3797
3798
3799 && it->c != '\n')
3800 {
3801 set_iterator_to_next (it, true);
3802 move_it_in_display_line_to (it, -1, -1, 0);
3803 }
3804
3805 it->continuation_lines_width += it->current_x;
3806 }
3807
3808
3809
3810
3811
3812 else if (it->current.dpvec_index >= 0)
3813 it->current.dpvec_index = 0;
3814
3815
3816
3817
3818 it->max_ascent = it->max_descent = 0;
3819 it->max_phys_ascent = it->max_phys_descent = 0;
3820
3821 it->current_y = first_y;
3822 it->vpos = 0;
3823 it->current_x = it->hpos = 0;
3824 }
3825 }
3826 }
3827
3828
3829
3830
3831
3832 static bool
3833 in_ellipses_for_invisible_text_p (struct display_pos *pos, struct window *w)
3834 {
3835 Lisp_Object prop, window;
3836 bool ellipses_p = false;
3837 ptrdiff_t charpos = CHARPOS (pos->pos);
3838
3839
3840
3841
3842
3843 if (pos->dpvec_index >= 0
3844 && pos->overlay_string_index < 0
3845 && CHARPOS (pos->string_pos) < 0
3846 && charpos > BEGV
3847 && (XSETWINDOW (window, w),
3848 prop = Fget_char_property (make_fixnum (charpos),
3849 Qinvisible, window),
3850 TEXT_PROP_MEANS_INVISIBLE (prop) == 0))
3851 {
3852 prop = Fget_char_property (make_fixnum (charpos - 1), Qinvisible,
3853 window);
3854 ellipses_p = 2 == TEXT_PROP_MEANS_INVISIBLE (prop);
3855 }
3856
3857 return ellipses_p;
3858 }
3859
3860
3861
3862
3863
3864
3865
3866 static bool
3867 init_from_display_pos (struct it *it, struct window *w, struct display_pos *pos)
3868 {
3869 ptrdiff_t charpos = CHARPOS (pos->pos), bytepos = BYTEPOS (pos->pos);
3870 int i;
3871 bool overlay_strings_with_newlines = false;
3872
3873
3874
3875
3876
3877 if (in_ellipses_for_invisible_text_p (pos, w))
3878 {
3879 --charpos;
3880 bytepos = 0;
3881 }
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892 init_iterator (it, w, charpos, bytepos, NULL, DEFAULT_FACE_ID);
3893
3894
3895
3896
3897 for (i = 0; i < it->n_overlay_strings && i < OVERLAY_STRING_CHUNK_SIZE; ++i)
3898 {
3899 const char *s = SSDATA (it->overlay_strings[i]);
3900 const char *e = s + SBYTES (it->overlay_strings[i]);
3901
3902 while (s < e && *s != '\n')
3903 ++s;
3904
3905 if (s < e)
3906 {
3907 overlay_strings_with_newlines = true;
3908 break;
3909 }
3910 }
3911
3912
3913
3914 if (pos->overlay_string_index >= 0)
3915 {
3916 int relative_index;
3917
3918
3919
3920
3921
3922 if (it->method == GET_FROM_IMAGE)
3923 pop_it (it);
3924
3925
3926
3927
3928 if (pos->overlay_string_index >= OVERLAY_STRING_CHUNK_SIZE)
3929 {
3930 ptrdiff_t n = pos->overlay_string_index / OVERLAY_STRING_CHUNK_SIZE;
3931 it->current.overlay_string_index = 0;
3932 while (n--)
3933 {
3934 load_overlay_strings (it, 0);
3935 it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE;
3936 }
3937 }
3938
3939 it->current.overlay_string_index = pos->overlay_string_index;
3940 relative_index = (it->current.overlay_string_index
3941 % OVERLAY_STRING_CHUNK_SIZE);
3942 it->string = it->overlay_strings[relative_index];
3943 eassert (STRINGP (it->string));
3944 it->current.string_pos = pos->string_pos;
3945 it->method = GET_FROM_STRING;
3946 it->end_charpos = SCHARS (it->string);
3947
3948 if (it->bidi_p)
3949 {
3950 it->bidi_it.string.lstring = it->string;
3951 it->bidi_it.string.s = NULL;
3952 it->bidi_it.string.schars = SCHARS (it->string);
3953 it->bidi_it.string.bufpos = it->overlay_strings_charpos;
3954 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
3955 it->bidi_it.string.unibyte = !it->multibyte_p;
3956 it->bidi_it.w = it->w;
3957 bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
3958 FRAME_WINDOW_P (it->f), &it->bidi_it);
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968 if (CHARPOS (pos->string_pos) == 0)
3969 {
3970 get_visually_first_element (it);
3971 if (IT_STRING_CHARPOS (*it) != 0)
3972 do {
3973
3974 eassert (it->bidi_it.charpos < it->bidi_it.string.schars);
3975 bidi_move_to_visually_next (&it->bidi_it);
3976 } while (it->bidi_it.charpos != 0);
3977 }
3978 eassert (IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
3979 && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos);
3980 }
3981 }
3982
3983 if (CHARPOS (pos->string_pos) >= 0)
3984 {
3985
3986
3987
3988 it->current.string_pos = pos->string_pos;
3989 eassert (STRINGP (it->string));
3990 if (it->bidi_p)
3991 bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
3992 FRAME_WINDOW_P (it->f), &it->bidi_it);
3993 }
3994
3995
3996
3997 if (pos->dpvec_index >= 0)
3998 {
3999 if (it->dpvec == NULL)
4000 get_next_display_element (it);
4001 eassert (it->dpvec && it->current.dpvec_index == 0);
4002 it->current.dpvec_index = pos->dpvec_index;
4003 }
4004
4005 CHECK_IT (it);
4006 return !overlay_strings_with_newlines;
4007 }
4008
4009
4010
4011
4012
4013 static void
4014 init_to_row_start (struct it *it, struct window *w, struct glyph_row *row)
4015 {
4016 init_from_display_pos (it, w, &row->start);
4017 it->start = row->start;
4018 it->continuation_lines_width = row->continuation_lines_width;
4019 CHECK_IT (it);
4020 }
4021
4022
4023
4024
4025
4026
4027
4028
4029 static bool
4030 init_to_row_end (struct it *it, struct window *w, struct glyph_row *row)
4031 {
4032 bool success = false;
4033
4034 if (init_from_display_pos (it, w, &row->end))
4035 {
4036 if (row->continued_p)
4037 it->continuation_lines_width
4038 = row->continuation_lines_width + row->pixel_width;
4039 CHECK_IT (it);
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049 if (get_next_display_element (it)
4050 && (it->bidi_it.scan_dir == -1 && it->cmp_it.id >= 0))
4051 success = false;
4052 else
4053 success = true;
4054 }
4055
4056 return success;
4057 }
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070 static void
4071 handle_stop (struct it *it)
4072 {
4073 enum prop_handled handled;
4074 bool handle_overlay_change_p;
4075 struct props *p;
4076
4077 it->dpvec = NULL;
4078 it->current.dpvec_index = -1;
4079 handle_overlay_change_p = !it->ignore_overlay_strings_at_pos_p;
4080 it->ellipsis_p = false;
4081
4082
4083 if (it->selective_display_ellipsis_p)
4084 it->saved_face_id = it->face_id;
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128 do
4129 {
4130 handled = HANDLED_NORMALLY;
4131
4132
4133 for (p = it_props; p->handler; ++p)
4134 {
4135 handled = p->handler (it);
4136
4137 if (handled == HANDLED_RECOMPUTE_PROPS)
4138 break;
4139 else if (handled == HANDLED_RETURN)
4140 {
4141
4142
4143 if (!handle_overlay_change_p
4144 || it->sp > 1
4145
4146
4147
4148
4149
4150
4151 || (it->current.overlay_string_index < 0
4152 && !get_overlay_strings_1 (it, 0, false)))
4153 {
4154 if (it->ellipsis_p)
4155 setup_for_ellipsis (it, 0);
4156
4157
4158
4159
4160
4161 if (STRINGP (it->string) && !SCHARS (it->string))
4162 pop_it (it);
4163 return;
4164 }
4165 else if (STRINGP (it->string) && !SCHARS (it->string))
4166 pop_it (it);
4167 else
4168 {
4169 it->string_from_display_prop_p = false;
4170 it->from_disp_prop_p = false;
4171 handle_overlay_change_p = false;
4172 }
4173 handled = HANDLED_RECOMPUTE_PROPS;
4174 break;
4175 }
4176 else if (handled == HANDLED_OVERLAY_STRING_CONSUMED)
4177 handle_overlay_change_p = false;
4178 }
4179
4180 if (handled != HANDLED_RECOMPUTE_PROPS)
4181 {
4182
4183
4184 if (it->method == GET_FROM_DISPLAY_VECTOR)
4185 handle_overlay_change_p = false;
4186
4187
4188
4189
4190 if (handle_overlay_change_p)
4191 handled = handle_overlay_change (it);
4192 }
4193
4194 if (it->ellipsis_p)
4195 {
4196 setup_for_ellipsis (it, 0);
4197 break;
4198 }
4199 }
4200 while (handled == HANDLED_RECOMPUTE_PROPS);
4201
4202
4203 if (handled == HANDLED_NORMALLY)
4204 compute_stop_pos (it);
4205 }
4206
4207
4208
4209
4210
4211 static void
4212 compute_stop_pos (struct it *it)
4213 {
4214 register INTERVAL iv, next_iv;
4215 Lisp_Object object, limit, position;
4216 ptrdiff_t charpos, bytepos, cmp_limit_pos = -1;
4217
4218 if (STRINGP (it->string))
4219 {
4220
4221
4222 it->stop_charpos = it->end_charpos;
4223 object = it->string;
4224 limit = Qnil;
4225 charpos = IT_STRING_CHARPOS (*it);
4226 bytepos = IT_STRING_BYTEPOS (*it);
4227 }
4228 else
4229 {
4230 ptrdiff_t pos;
4231
4232
4233
4234 if (it->end_charpos > ZV)
4235 it->end_charpos = ZV;
4236 it->stop_charpos = it->end_charpos;
4237
4238
4239
4240
4241
4242 charpos = IT_CHARPOS (*it);
4243 bytepos = IT_BYTEPOS (*it);
4244 pos = next_overlay_change (charpos);
4245 if (pos < it->stop_charpos)
4246 it->stop_charpos = pos;
4247
4248 if (!NILP (BVAR (current_buffer, enable_multibyte_characters))
4249 && !NILP (Vauto_composition_mode)
4250 && composition_break_at_point
4251 && charpos < PT && PT < it->stop_charpos)
4252 it->stop_charpos = PT;
4253
4254
4255
4256 XSETBUFFER (object, current_buffer);
4257 pos = charpos + TEXT_PROP_DISTANCE_LIMIT;
4258
4259
4260
4261
4262
4263
4264 if (!composition_break_at_point
4265 && !NILP (BVAR (current_buffer, enable_multibyte_characters))
4266 && !NILP (Vauto_composition_mode))
4267 {
4268 ptrdiff_t endpos = charpos + 10 * TEXT_PROP_DISTANCE_LIMIT;
4269 bool found = false;
4270
4271 if (pos > ZV)
4272 pos = ZV;
4273 if (endpos > ZV)
4274 endpos = ZV;
4275 ptrdiff_t bpos = CHAR_TO_BYTE (pos);
4276 while (pos < endpos)
4277 {
4278 int ch = fetch_char_advance_no_check (&pos, &bpos);
4279 if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\f')
4280 {
4281 found = true;
4282 break;
4283 }
4284 }
4285 if (found)
4286 {
4287 pos--;
4288 cmp_limit_pos = pos;
4289 }
4290 else if (it->stop_charpos < endpos)
4291 pos = it->stop_charpos;
4292 else
4293 {
4294
4295 pos = charpos + TEXT_PROP_DISTANCE_LIMIT;
4296 }
4297 }
4298 limit = make_fixnum (pos);
4299 }
4300
4301
4302
4303 position = make_fixnum (charpos);
4304 iv = validate_interval_range (object, &position, &position, false);
4305 if (iv)
4306 {
4307 Lisp_Object values_here[LAST_PROP_IDX];
4308 struct props *p;
4309
4310
4311 for (p = it_props; p->handler; ++p)
4312 values_here[p->idx] = textget (iv->plist,
4313 builtin_lisp_symbol (p->name));
4314
4315
4316
4317 for (next_iv = next_interval (iv);
4318 (next_iv
4319 && (NILP (limit)
4320 || XFIXNAT (limit) > next_iv->position));
4321 next_iv = next_interval (next_iv))
4322 {
4323 for (p = it_props; p->handler; ++p)
4324 {
4325 Lisp_Object new_value = textget (next_iv->plist,
4326 builtin_lisp_symbol (p->name));
4327 if (!EQ (values_here[p->idx], new_value))
4328 break;
4329 }
4330
4331 if (p->handler)
4332 break;
4333 }
4334
4335 if (next_iv)
4336 {
4337 if (FIXNUMP (limit)
4338 && next_iv->position >= XFIXNAT (limit))
4339
4340 it->stop_charpos = min (XFIXNAT (limit), it->stop_charpos);
4341 else
4342
4343 it->stop_charpos = min (it->stop_charpos, next_iv->position);
4344 }
4345 }
4346
4347 if (it->cmp_it.id < 0
4348 && (STRINGP (it->string)
4349 || ((!it->bidi_p || it->bidi_it.scan_dir >= 0)
4350 && it->cmp_it.stop_pos <= IT_CHARPOS (*it))))
4351 {
4352 ptrdiff_t stoppos = it->end_charpos;
4353
4354
4355
4356
4357 if (it->bidi_p && it->bidi_it.scan_dir < 0)
4358 stoppos = -1;
4359 else if (cmp_limit_pos > 0)
4360 stoppos = cmp_limit_pos;
4361
4362
4363
4364 composition_compute_stop_pos (&it->cmp_it, charpos, bytepos,
4365 stoppos, it->string, false);
4366 }
4367
4368 eassert (STRINGP (it->string)
4369 || (it->stop_charpos >= BEGV
4370 && it->stop_charpos >= IT_CHARPOS (*it)));
4371 }
4372
4373
4374
4375
4376 #define MAX_DISP_SCAN 250
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390 ptrdiff_t
4391 compute_display_string_pos (struct text_pos *position,
4392 struct bidi_string_data *string,
4393 struct window *w,
4394 bool frame_window_p, int *disp_prop)
4395 {
4396
4397 Lisp_Object object, object1;
4398 Lisp_Object pos, spec, limpos;
4399 bool string_p = string && (STRINGP (string->lstring) || string->s);
4400 ptrdiff_t eob = string_p ? string->schars : ZV;
4401 ptrdiff_t begb = string_p ? 0 : BEGV;
4402 ptrdiff_t bufpos, charpos = CHARPOS (*position);
4403 ptrdiff_t lim =
4404 (charpos < eob - MAX_DISP_SCAN) ? charpos + MAX_DISP_SCAN : eob;
4405 struct text_pos tpos;
4406 int rv = 0;
4407
4408 if (string && STRINGP (string->lstring))
4409 object1 = object = string->lstring;
4410 else if (w && !string_p)
4411 {
4412 XSETWINDOW (object, w);
4413 object1 = Qnil;
4414 }
4415 else
4416 object1 = object = Qnil;
4417
4418 *disp_prop = 1;
4419
4420 if (charpos >= eob
4421
4422
4423 || string->from_disp_str
4424
4425 || (string->s && !STRINGP (object)))
4426 {
4427 *disp_prop = 0;
4428 return eob;
4429 }
4430
4431
4432
4433 pos = make_fixnum (charpos);
4434 if (STRINGP (object))
4435 bufpos = string->bufpos;
4436 else
4437 bufpos = charpos;
4438 tpos = *position;
4439 if (!NILP (spec = Fget_char_property (pos, Qdisplay, object))
4440 && (charpos <= begb
4441 || !EQ (Fget_char_property (make_fixnum (charpos - 1), Qdisplay,
4442 object),
4443 spec))
4444 && (rv = handle_display_spec (NULL, spec, object1, Qnil, &tpos, bufpos,
4445 frame_window_p)))
4446 {
4447 if (rv == 2)
4448 *disp_prop = 2;
4449 return charpos;
4450 }
4451
4452
4453
4454 limpos = make_fixnum (lim);
4455 do {
4456 pos = Fnext_single_char_property_change (pos, Qdisplay, object1, limpos);
4457 CHARPOS (tpos) = XFIXNAT (pos);
4458 if (CHARPOS (tpos) >= lim)
4459 {
4460 *disp_prop = 0;
4461 break;
4462 }
4463 if (STRINGP (object))
4464 BYTEPOS (tpos) = string_char_to_byte (object, CHARPOS (tpos));
4465 else
4466 BYTEPOS (tpos) = CHAR_TO_BYTE (CHARPOS (tpos));
4467 spec = Fget_char_property (pos, Qdisplay, object);
4468 if (!STRINGP (object))
4469 bufpos = CHARPOS (tpos);
4470 } while (NILP (spec)
4471 || !(rv = handle_display_spec (NULL, spec, object1, Qnil, &tpos,
4472 bufpos, frame_window_p)));
4473 if (rv == 2)
4474 *disp_prop = 2;
4475
4476 return CHARPOS (tpos);
4477 }
4478
4479
4480
4481
4482
4483
4484 ptrdiff_t
4485 compute_display_string_end (ptrdiff_t charpos, struct bidi_string_data *string)
4486 {
4487
4488 Lisp_Object object =
4489 (string && STRINGP (string->lstring)) ? string->lstring : Qnil;
4490 Lisp_Object pos = make_fixnum (charpos);
4491 ptrdiff_t eob =
4492 (STRINGP (object) || (string && string->s)) ? string->schars : ZV;
4493
4494 if (charpos >= eob || (string->s && !STRINGP (object)))
4495 return eob;
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511 if (NILP (Fget_char_property (pos, Qdisplay, object)))
4512 return -1;
4513
4514
4515
4516 pos = Fnext_single_char_property_change (pos, Qdisplay, object, Qnil);
4517
4518 return XFIXNAT (pos);
4519 }
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531 static enum prop_handled
4532 handle_fontified_prop (struct it *it)
4533 {
4534 Lisp_Object prop, pos;
4535 enum prop_handled handled = HANDLED_NORMALLY;
4536
4537 if (!NILP (Vmemory_full))
4538 return handled;
4539
4540
4541
4542
4543
4544 if (!STRINGP (it->string)
4545 && it->s == NULL
4546 && !NILP (Vfontification_functions)
4547 && !(input_was_pending && redisplay_skip_fontification_on_input)
4548 && !NILP (Vrun_hooks)
4549 && (pos = make_fixnum (IT_CHARPOS (*it)),
4550 prop = Fget_char_property (pos, Qfontified, Qnil),
4551
4552
4553 NILP (prop) && IT_CHARPOS (*it) < Z))
4554 {
4555 specpdl_ref count = SPECPDL_INDEX ();
4556 Lisp_Object val;
4557 struct buffer *obuf = current_buffer;
4558 ptrdiff_t begv = BEGV, zv = ZV;
4559 bool old_clip_changed = current_buffer->clip_changed;
4560 bool saved_inhibit_flag = it->f->inhibit_clear_image_cache;
4561
4562 val = Vfontification_functions;
4563 specbind (Qfontification_functions, Qnil);
4564
4565 eassert (it->end_charpos == ZV);
4566
4567 if (current_buffer->long_line_optimizations_p
4568 && long_line_optimizations_region_size > 0)
4569 {
4570 ptrdiff_t begv = it->large_narrowing_begv;
4571 ptrdiff_t zv = it->large_narrowing_zv;
4572 ptrdiff_t charpos = IT_CHARPOS (*it);
4573 if (charpos < begv || charpos > zv)
4574 {
4575 begv = get_large_narrowing_begv (charpos);
4576 zv = get_large_narrowing_zv (charpos);
4577 }
4578 if (begv != BEG || zv != Z)
4579 labeled_narrow_to_region (make_fixnum (begv), make_fixnum (zv),
4580 Qlong_line_optimizations_in_fontification_functions);
4581 }
4582
4583
4584
4585 it->f->inhibit_clear_image_cache = true;
4586
4587 if (!CONSP (val) || EQ (XCAR (val), Qlambda))
4588 safe_call1 (val, pos);
4589 else
4590 {
4591 Lisp_Object fns, fn;
4592
4593 fns = Qnil;
4594
4595 for (; CONSP (val); val = XCDR (val))
4596 {
4597 fn = XCAR (val);
4598
4599 if (EQ (fn, Qt))
4600 {
4601
4602
4603
4604
4605
4606 for (fns = Fdefault_value (Qfontification_functions);
4607 CONSP (fns);
4608 fns = XCDR (fns))
4609 {
4610 fn = XCAR (fns);
4611 if (!EQ (fn, Qt))
4612 safe_call1 (fn, pos);
4613 }
4614 }
4615 else
4616 safe_call1 (fn, pos);
4617 }
4618 }
4619
4620 it->f->inhibit_clear_image_cache = saved_inhibit_flag;
4621 unbind_to (count, Qnil);
4622
4623
4624
4625
4626
4627
4628
4629
4630 if (obuf == current_buffer)
4631 {
4632 if (begv == BEGV && zv == ZV)
4633 current_buffer->clip_changed = old_clip_changed;
4634 }
4635
4636
4637 else if (BUFFER_LIVE_P (obuf))
4638 set_buffer_internal_1 (obuf);
4639
4640
4641
4642
4643
4644
4645 it->end_charpos = ZV;
4646
4647
4648
4649
4650 if (!NILP (Fget_char_property (pos, Qfontified, Qnil)))
4651 handled = HANDLED_RECOMPUTE_PROPS;
4652 }
4653
4654 return handled;
4655 }
4656
4657
4658
4659
4660
4661
4662
4663 static int
4664 face_at_pos (const struct it *it, enum lface_attribute_index attr_filter)
4665 {
4666 ptrdiff_t next_stop;
4667
4668 if (!STRINGP (it->string))
4669 {
4670 return face_at_buffer_position (it->w,
4671 IT_CHARPOS (*it),
4672 &next_stop,
4673 (IT_CHARPOS (*it)
4674 + TEXT_PROP_DISTANCE_LIMIT),
4675 false, it->base_face_id,
4676 attr_filter);
4677 }
4678 else
4679 {
4680 int base_face_id;
4681 ptrdiff_t bufpos;
4682 int i;
4683 Lisp_Object from_overlay
4684 = (it->current.overlay_string_index >= 0
4685 ? it->string_overlays[it->current.overlay_string_index
4686 % OVERLAY_STRING_CHUNK_SIZE]
4687 : Qnil);
4688
4689
4690
4691
4692
4693
4694
4695 if (! NILP (from_overlay))
4696 for (i = it->sp - 1; i >= 0; i--)
4697 {
4698 if (it->stack[i].current.overlay_string_index >= 0)
4699 from_overlay
4700 = it->string_overlays[it->stack[i].current.overlay_string_index
4701 % OVERLAY_STRING_CHUNK_SIZE];
4702 else if (! NILP (it->stack[i].from_overlay))
4703 from_overlay = it->stack[i].from_overlay;
4704
4705 if (!NILP (from_overlay))
4706 break;
4707 }
4708
4709 if (! NILP (from_overlay))
4710 {
4711 bufpos = IT_CHARPOS (*it);
4712
4713
4714 base_face_id
4715 = face_for_overlay_string (it->w,
4716 IT_CHARPOS (*it),
4717 &next_stop,
4718 (IT_CHARPOS (*it)
4719 + TEXT_PROP_DISTANCE_LIMIT),
4720 false,
4721 from_overlay, attr_filter);
4722 }
4723 else
4724 {
4725 bufpos = 0;
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743 base_face_id = it->string_from_prefix_prop_p
4744 ? (!NILP (Vface_remapping_alist)
4745 ? lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
4746 : DEFAULT_FACE_ID)
4747 : underlying_face_id (it);
4748 }
4749
4750 return face_at_string_position (it->w,
4751 it->string,
4752 IT_STRING_CHARPOS (*it),
4753 bufpos,
4754 &next_stop,
4755 base_face_id, false,
4756 attr_filter);
4757 }
4758 }
4759
4760
4761
4762
4763 static enum prop_handled
4764 handle_face_prop (struct it *it)
4765 {
4766 specpdl_ref count = SPECPDL_INDEX ();
4767
4768
4769
4770 specbind (Qinhibit_quit, Qt);
4771 const int new_face_id = face_at_pos (it, 0);
4772 unbind_to (count, Qnil);
4773
4774
4775
4776
4777
4778
4779
4780
4781 if (new_face_id != it->face_id)
4782 {
4783 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
4784
4785
4786
4787 struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
4788
4789
4790
4791
4792 if (!STRINGP (it->string)
4793 && !old_face
4794 && IT_CHARPOS (*it) > BEG)
4795 {
4796 const int prev_face_id = face_before_it_pos (it);
4797
4798 old_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
4799 }
4800
4801
4802
4803
4804 it->face_id = new_face_id;
4805
4806
4807 if (!(it->start_of_box_run_p && old_face && old_face->box))
4808 it->start_of_box_run_p = (new_face->box != FACE_NO_BOX
4809 && (old_face == NULL || !old_face->box));
4810 it->face_box_p = new_face->box != FACE_NO_BOX;
4811 }
4812
4813 return HANDLED_NORMALLY;
4814 }
4815
4816
4817
4818
4819
4820
4821
4822 static int
4823 underlying_face_id (const struct it *it)
4824 {
4825 int face_id = it->base_face_id, i;
4826
4827 eassert (STRINGP (it->string));
4828
4829 for (i = it->sp - 1; i >= 0; --i)
4830 if (NILP (it->stack[i].string))
4831 face_id = it->stack[i].face_id;
4832
4833 return face_id;
4834 }
4835
4836
4837
4838
4839
4840
4841
4842 static int
4843 face_before_or_after_it_pos (struct it *it, bool before_p)
4844 {
4845 int face_id, limit;
4846 ptrdiff_t next_check_charpos;
4847 struct it it_copy;
4848 void *it_copy_data = NULL;
4849
4850 eassert (it->s == NULL);
4851
4852 if (STRINGP (it->string))
4853 {
4854 ptrdiff_t bufpos, charpos;
4855 int base_face_id;
4856
4857
4858
4859
4860
4861 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string)
4862 || (IT_STRING_CHARPOS (*it) == 0 && before_p)
4863 || it->current_x <= it->first_visible_x)
4864 return it->face_id;
4865
4866 if (!it->bidi_p)
4867 {
4868
4869
4870
4871 if (before_p)
4872 charpos = IT_STRING_CHARPOS (*it) - 1;
4873 else if (it->what == IT_COMPOSITION)
4874
4875
4876 charpos = IT_STRING_CHARPOS (*it) + it->cmp_it.nchars;
4877 else
4878 charpos = IT_STRING_CHARPOS (*it) + 1;
4879 }
4880 else
4881 {
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892 SAVE_IT (it_copy, *it, it_copy_data);
4893 IT_STRING_CHARPOS (it_copy) = 0;
4894 bidi_init_it (0, 0, FRAME_WINDOW_P (it_copy.f), &it_copy.bidi_it);
4895 it_copy.bidi_it.scan_dir = 0;
4896
4897 do
4898 {
4899 charpos = it_copy.bidi_it.charpos;
4900 if (charpos >= SCHARS (it->string))
4901 break;
4902 bidi_move_to_visually_next (&it_copy.bidi_it);
4903 }
4904 while (it_copy.bidi_it.charpos != IT_STRING_CHARPOS (*it));
4905
4906 if (!before_p)
4907 {
4908
4909
4910
4911 int n = (it->what == IT_COMPOSITION ? it->cmp_it.nchars : 1);
4912
4913
4914
4915 if (it_copy.bidi_it.first_elt)
4916 n++;
4917 while (n--)
4918 bidi_move_to_visually_next (&it_copy.bidi_it);
4919
4920 charpos = it_copy.bidi_it.charpos;
4921 }
4922
4923 RESTORE_IT (it, it, it_copy_data);
4924 }
4925 eassert (0 <= charpos && charpos <= SCHARS (it->string));
4926
4927 if (it->current.overlay_string_index >= 0)
4928 bufpos = IT_CHARPOS (*it);
4929 else
4930 bufpos = 0;
4931
4932 base_face_id = underlying_face_id (it);
4933
4934
4935 face_id = face_at_string_position (it->w, it->string, charpos,
4936 bufpos, &next_check_charpos,
4937 base_face_id, false, 0);
4938
4939
4940
4941
4942 if (STRING_MULTIBYTE (it->string))
4943 {
4944 struct text_pos pos1 = string_pos (charpos, it->string);
4945 const unsigned char *p = SDATA (it->string) + BYTEPOS (pos1);
4946 struct face *face = FACE_FROM_ID (it->f, face_id);
4947 int len, c = check_char_and_length (p, &len);
4948 face_id = FACE_FOR_CHAR (it->f, face, c, charpos, it->string);
4949 }
4950 }
4951 else
4952 {
4953 struct text_pos pos;
4954
4955 if ((IT_CHARPOS (*it) >= ZV && !before_p)
4956 || (IT_CHARPOS (*it) <= BEGV && before_p))
4957 return it->face_id;
4958
4959 limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT;
4960 pos = it->current.pos;
4961
4962 if (!it->bidi_p)
4963 {
4964 if (before_p)
4965 DEC_TEXT_POS (pos, it->multibyte_p);
4966 else
4967 {
4968 if (it->what == IT_COMPOSITION)
4969 {
4970
4971
4972 pos.charpos += it->cmp_it.nchars;
4973 pos.bytepos += it->len;
4974 }
4975 else
4976 INC_TEXT_POS (pos, it->multibyte_p);
4977 }
4978 }
4979 else
4980 {
4981 if (before_p)
4982 {
4983 int current_x;
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994 if (it->current_x <= it->first_visible_x)
4995 return it->face_id;
4996 SAVE_IT (it_copy, *it, it_copy_data);
4997
4998
4999
5000
5001
5002 current_x = it_copy.current_x;
5003 move_it_vertically_backward (&it_copy, 0);
5004 move_it_in_display_line (&it_copy, ZV, current_x - 1, MOVE_TO_X);
5005 pos = it_copy.current.pos;
5006 RESTORE_IT (it, it, it_copy_data);
5007 }
5008 else
5009 {
5010
5011
5012
5013 int n = (it->what == IT_COMPOSITION ? it->cmp_it.nchars : 1);
5014
5015 it_copy = *it;
5016
5017
5018
5019 if (it->bidi_it.first_elt)
5020 n++;
5021 while (n--)
5022 bidi_move_to_visually_next (&it_copy.bidi_it);
5023
5024 SET_TEXT_POS (pos,
5025 it_copy.bidi_it.charpos, it_copy.bidi_it.bytepos);
5026 }
5027 }
5028 eassert (BEGV <= CHARPOS (pos) && CHARPOS (pos) <= ZV);
5029
5030
5031 face_id = face_at_buffer_position (it->w,
5032 CHARPOS (pos),
5033 &next_check_charpos,
5034 limit, false, -1, 0);
5035
5036
5037
5038
5039 if (it->multibyte_p)
5040 {
5041 int c = FETCH_MULTIBYTE_CHAR (BYTEPOS (pos));
5042 struct face *face = FACE_FROM_ID (it->f, face_id);
5043 face_id = FACE_FOR_CHAR (it->f, face, c, CHARPOS (pos), Qnil);
5044 }
5045 }
5046
5047 return face_id;
5048 }
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059 static enum prop_handled
5060 handle_invisible_prop (struct it *it)
5061 {
5062 enum prop_handled handled = HANDLED_NORMALLY;
5063 int invis;
5064 Lisp_Object prop;
5065
5066 if (STRINGP (it->string))
5067 {
5068 Lisp_Object end_charpos, limit;
5069
5070
5071
5072
5073 end_charpos = make_fixnum (IT_STRING_CHARPOS (*it));
5074 prop = Fget_text_property (end_charpos, Qinvisible, it->string);
5075 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5076
5077 if (invis != 0 && IT_STRING_CHARPOS (*it) < it->end_charpos)
5078 {
5079
5080
5081 bool display_ellipsis_p = (invis == 2);
5082 ptrdiff_t len, endpos;
5083
5084 handled = HANDLED_RECOMPUTE_PROPS;
5085
5086
5087
5088 endpos = len = SCHARS (it->string);
5089 XSETINT (limit, len);
5090 do
5091 {
5092 end_charpos
5093 = Fnext_single_property_change (end_charpos, Qinvisible,
5094 it->string, limit);
5095
5096
5097 eassert (FIXNUMP (end_charpos));
5098 if (FIXNUMP (end_charpos))
5099 {
5100 endpos = XFIXNAT (end_charpos);
5101 prop = Fget_text_property (end_charpos, Qinvisible, it->string);
5102 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5103 if (invis == 2)
5104 display_ellipsis_p = true;
5105 }
5106 else
5107 endpos = len;
5108 }
5109 while (invis != 0 && endpos < len);
5110
5111 if (display_ellipsis_p)
5112 it->ellipsis_p = true;
5113
5114 if (endpos < len)
5115 {
5116
5117 struct text_pos old;
5118 ptrdiff_t oldpos;
5119
5120 old = it->current.string_pos;
5121 oldpos = CHARPOS (old);
5122 if (it->bidi_p)
5123 {
5124 if (it->bidi_it.first_elt
5125 && it->bidi_it.charpos < SCHARS (it->string))
5126 bidi_paragraph_init (it->paragraph_embedding,
5127 &it->bidi_it, true);
5128
5129 do
5130 {
5131 bidi_move_to_visually_next (&it->bidi_it);
5132 }
5133 while (oldpos <= it->bidi_it.charpos
5134 && it->bidi_it.charpos < endpos
5135 && it->bidi_it.charpos < it->bidi_it.string.schars);
5136
5137 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
5138 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
5139 if (IT_CHARPOS (*it) >= endpos)
5140 it->prev_stop = endpos;
5141 }
5142 else
5143 {
5144 IT_STRING_CHARPOS (*it) = endpos;
5145 compute_string_pos (&it->current.string_pos, old, it->string);
5146 }
5147 }
5148 else
5149 {
5150
5151
5152
5153 if (it->current.overlay_string_index >= 0
5154 && !display_ellipsis_p)
5155 {
5156 next_overlay_string (it);
5157
5158
5159 handled = HANDLED_OVERLAY_STRING_CONSUMED;
5160 }
5161 else
5162 {
5163 IT_STRING_CHARPOS (*it) = SCHARS (it->string);
5164 IT_STRING_BYTEPOS (*it) = SBYTES (it->string);
5165 }
5166 }
5167 }
5168 }
5169 else
5170 {
5171 ptrdiff_t newpos, next_stop, start_charpos, tem;
5172 Lisp_Object pos, overlay;
5173
5174
5175 tem = start_charpos = IT_CHARPOS (*it);
5176 pos = make_fixnum (tem);
5177 prop = get_char_property_and_overlay (pos, Qinvisible, it->window,
5178 &overlay);
5179 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5180
5181
5182 if (invis != 0 && start_charpos < it->end_charpos)
5183 {
5184
5185
5186 bool display_ellipsis_p = invis == 2;
5187
5188 handled = HANDLED_RECOMPUTE_PROPS;
5189
5190
5191
5192 do
5193 {
5194
5195
5196
5197
5198
5199 newpos = skip_invisible (tem, &next_stop, ZV, it->window);
5200
5201
5202
5203
5204 if (newpos == tem || newpos >= ZV)
5205 invis = 0;
5206 else
5207 {
5208
5209
5210
5211
5212
5213
5214 pos = make_fixnum (newpos);
5215 prop = Fget_char_property (pos, Qinvisible, it->window);
5216 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5217 }
5218
5219
5220
5221 if (invis != 0)
5222 tem = next_stop;
5223
5224
5225
5226 if (invis == 2)
5227 display_ellipsis_p = true;
5228 }
5229 while (invis != 0);
5230
5231
5232 if (it->bidi_p)
5233 {
5234 ptrdiff_t bpos = CHAR_TO_BYTE (newpos);
5235 bool on_newline
5236 = bpos == ZV_BYTE || FETCH_BYTE (bpos) == '\n';
5237 bool after_newline
5238 = newpos <= BEGV || FETCH_BYTE (bpos - 1) == '\n';
5239
5240
5241
5242
5243
5244
5245
5246
5247 if (on_newline || after_newline)
5248 {
5249 struct text_pos tpos;
5250 bidi_dir_t pdir = it->bidi_it.paragraph_dir;
5251
5252 SET_TEXT_POS (tpos, newpos, bpos);
5253 reseat_1 (it, tpos, false);
5254
5255
5256
5257
5258
5259 if (on_newline)
5260 {
5261 it->bidi_it.first_elt = false;
5262 it->bidi_it.paragraph_dir = pdir;
5263 it->bidi_it.ch = (bpos == ZV_BYTE) ? -1 : '\n';
5264 it->bidi_it.nchars = 1;
5265 it->bidi_it.ch_len = 1;
5266 }
5267 }
5268 else
5269 {
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280 if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV)
5281 {
5282
5283
5284
5285
5286
5287
5288
5289 bidi_paragraph_init (it->paragraph_embedding,
5290 &it->bidi_it, true);
5291 }
5292 do
5293 {
5294 bidi_move_to_visually_next (&it->bidi_it);
5295 }
5296 while (it->stop_charpos <= it->bidi_it.charpos
5297 && it->bidi_it.charpos < newpos);
5298 IT_CHARPOS (*it) = it->bidi_it.charpos;
5299 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
5300
5301
5302
5303
5304 if (IT_CHARPOS (*it) >= newpos)
5305 it->prev_stop = newpos;
5306 }
5307 }
5308 else
5309 {
5310 IT_CHARPOS (*it) = newpos;
5311 IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos);
5312 }
5313
5314 if (display_ellipsis_p)
5315 {
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328 if (!STRINGP (it->object))
5329 {
5330 it->position.charpos = newpos - 1;
5331 it->position.bytepos = CHAR_TO_BYTE (it->position.charpos);
5332 }
5333 }
5334
5335
5336
5337
5338
5339
5340
5341 if (NILP (overlay)
5342 && get_overlay_strings (it, it->stop_charpos))
5343 {
5344 handled = HANDLED_RECOMPUTE_PROPS;
5345 if (it->sp > 0)
5346 {
5347 it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360 it->stack[it->sp - 1].stop_charpos
5361 = CHARPOS (it->stack[it->sp - 1].current.pos);
5362 }
5363 }
5364 else if (display_ellipsis_p)
5365 {
5366 it->ellipsis_p = true;
5367
5368
5369
5370 handled = HANDLED_RETURN;
5371 }
5372 }
5373 }
5374
5375 return handled;
5376 }
5377
5378
5379
5380
5381
5382 static void
5383 setup_for_ellipsis (struct it *it, int len)
5384 {
5385
5386
5387 if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
5388 {
5389 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
5390 it->dpvec = v->contents;
5391 it->dpend = v->contents + v->header.size;
5392 }
5393 else
5394 {
5395
5396 it->dpvec = default_invis_vector;
5397 it->dpend = default_invis_vector + 3;
5398 }
5399
5400 it->dpvec_char_len = len;
5401 it->current.dpvec_index = 0;
5402 it->dpvec_face_id = -1;
5403
5404
5405
5406
5407
5408
5409
5410
5411 if (it->saved_face_id >= 0)
5412 it->face_id = it->saved_face_id;
5413
5414
5415
5416 if (it->method == GET_FROM_BUFFER)
5417 it->ignore_overlay_strings_at_pos_p = false;
5418
5419 it->method = GET_FROM_DISPLAY_VECTOR;
5420 it->ellipsis_p = true;
5421 }
5422
5423
5424 static Lisp_Object
5425 find_display_property (Lisp_Object disp, Lisp_Object prop)
5426 {
5427 if (NILP (disp))
5428 return Qnil;
5429
5430 if (VECTORP (disp))
5431 {
5432 for (ptrdiff_t i = 0; i < ASIZE (disp); i++)
5433 {
5434 Lisp_Object elem = AREF (disp, i);
5435 if (CONSP (elem)
5436 && CONSP (XCDR (elem))
5437 && EQ (XCAR (elem), prop))
5438 return XCAR (XCDR (elem));
5439 }
5440 return Qnil;
5441 }
5442
5443 else if (CONSP (disp)
5444 && CONSP (XCAR (disp)))
5445 {
5446 while (!NILP (disp))
5447 {
5448 Lisp_Object elem = XCAR (disp);
5449 if (CONSP (elem)
5450 && CONSP (XCDR (elem))
5451 && EQ (XCAR (elem), prop))
5452 return XCAR (XCDR (elem));
5453
5454
5455
5456 if (CONSP (XCDR (disp)))
5457 disp = XCDR (disp);
5458 else
5459 disp = Qnil;
5460 }
5461 return Qnil;
5462 }
5463
5464 else if (CONSP (disp)
5465 && CONSP (XCDR (disp))
5466 && EQ (XCAR (disp), prop))
5467 return XCAR (XCDR (disp));
5468 else
5469 return Qnil;
5470 }
5471
5472 static Lisp_Object
5473 get_display_property (ptrdiff_t bufpos, Lisp_Object prop, Lisp_Object object)
5474 {
5475 return find_display_property (Fget_text_property (make_fixnum (bufpos),
5476 Qdisplay, object),
5477 prop);
5478 }
5479
5480 static void
5481 display_min_width (struct it *it, ptrdiff_t bufpos,
5482 Lisp_Object object, Lisp_Object width_spec)
5483 {
5484
5485
5486 if (!NILP (it->min_width_property)
5487 && !EQ (width_spec, it->min_width_property))
5488 {
5489 if (!it->glyph_row)
5490 return;
5491
5492
5493
5494
5495
5496 if ((bufpos == 0
5497 && !EQ (it->min_width_property,
5498 get_display_property (0, Qmin_width, object)))
5499
5500
5501 || (bufpos > BEGV
5502 && EQ (it->min_width_property,
5503 get_display_property (bufpos - 1, Qmin_width, object))))
5504 {
5505 Lisp_Object w = Qnil;
5506 double width;
5507 #ifdef HAVE_WINDOW_SYSTEM
5508 if (FRAME_WINDOW_P (it->f))
5509 {
5510 struct font *font = NULL;
5511 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5512 font = face->font ? face->font : FRAME_FONT (it->f);
5513 calc_pixel_width_or_height (&width, it,
5514 XCAR (it->min_width_property),
5515 font, true, NULL);
5516 width -= it->current_x - it->min_width_start;
5517 w = list1 (make_int (width));
5518 }
5519 else
5520 #endif
5521 {
5522 calc_pixel_width_or_height (&width, it,
5523 XCAR (it->min_width_property),
5524 NULL, true, NULL);
5525 width -= (it->current_x - it->min_width_start) /
5526 FRAME_COLUMN_WIDTH (it->f);
5527 w = make_int (width);
5528 }
5529
5530
5531 it->object = list3 (Qspace, QCwidth, w);
5532 produce_stretch_glyph (it);
5533 if (it->area == TEXT_AREA)
5534 it->current_x += it->pixel_width;
5535 it->min_width_property = Qnil;
5536 }
5537 }
5538
5539
5540
5541
5542 if (CONSP (width_spec))
5543 {
5544 if (bufpos == BEGV
5545
5546 || (bufpos == 0
5547 && !EQ (it->min_width_property,
5548 get_display_property (0, Qmin_width, object)))
5549
5550 || (bufpos > BEGV
5551 && !EQ (width_spec,
5552 get_display_property (bufpos - 1, Qmin_width, object))))
5553 {
5554 it->min_width_property = width_spec;
5555 it->min_width_start = it->current_x;
5556 }
5557 }
5558 }
5559
5560 DEFUN ("get-display-property", Fget_display_property,
5561 Sget_display_property, 2, 4, 0,
5562 doc:
5563
5564
5565
5566
5567 )
5568 (Lisp_Object position, Lisp_Object prop, Lisp_Object object,
5569 Lisp_Object properties)
5570 {
5571 if (NILP (properties))
5572 properties = Fget_text_property (position, Qdisplay, object);
5573 else
5574 CHECK_LIST (properties);
5575
5576 return find_display_property (properties, prop);
5577 }
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591 static enum prop_handled
5592 handle_display_prop (struct it *it)
5593 {
5594 Lisp_Object propval, object, overlay;
5595 struct text_pos *position;
5596 ptrdiff_t bufpos;
5597
5598 int display_replaced = 0;
5599
5600 if (STRINGP (it->string))
5601 {
5602 object = it->string;
5603 position = &it->current.string_pos;
5604 bufpos = CHARPOS (it->current.pos);
5605 }
5606 else
5607 {
5608 XSETWINDOW (object, it->w);
5609 position = &it->current.pos;
5610 bufpos = CHARPOS (*position);
5611 }
5612
5613
5614 it->slice.x = it->slice.y = it->slice.width = it->slice.height = Qnil;
5615 it->space_width = Qnil;
5616 it->font_height = Qnil;
5617 it->voffset = 0;
5618
5619
5620
5621
5622 if (!it->string_from_display_prop_p)
5623 it->area = TEXT_AREA;
5624
5625 propval = get_char_property_and_overlay (make_fixnum (position->charpos),
5626 Qdisplay, object, &overlay);
5627
5628
5629 if (!STRINGP (it->string))
5630 object = it->w->contents;
5631
5632
5633 if (!NILP (it->min_width_property)
5634 && NILP (find_display_property (propval, Qmin_width)))
5635 display_min_width (it, bufpos, object, Qnil);
5636
5637 if (NILP (propval))
5638 return HANDLED_NORMALLY;
5639
5640
5641
5642 display_replaced = handle_display_spec (it, propval, object, overlay,
5643 position, bufpos,
5644 FRAME_WINDOW_P (it->f));
5645 return display_replaced != 0 ? HANDLED_RETURN : HANDLED_NORMALLY;
5646 }
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664 static int
5665 handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5666 Lisp_Object overlay, struct text_pos *position,
5667 ptrdiff_t bufpos, bool frame_window_p)
5668 {
5669 int replacing = 0;
5670 bool enable_eval = true;
5671
5672
5673 if (CONSP (spec) && EQ (XCAR (spec), Qdisable_eval))
5674 {
5675 enable_eval = false;
5676 spec = CONSP (XCDR (spec)) ? XCAR (XCDR (spec)) : Qnil;
5677 }
5678
5679 if (CONSP (spec)
5680
5681 && !EQ (XCAR (spec), Qimage)
5682 #ifdef HAVE_XWIDGETS
5683 && !EQ (XCAR (spec), Qxwidget)
5684 #endif
5685 && !EQ (XCAR (spec), Qspace)
5686 && !EQ (XCAR (spec), Qwhen)
5687 && !EQ (XCAR (spec), Qslice)
5688 && !EQ (XCAR (spec), Qspace_width)
5689 && !EQ (XCAR (spec), Qheight)
5690 && !EQ (XCAR (spec), Qraise)
5691
5692 && !(CONSP (XCAR (spec)) && EQ (XCAR (XCAR (spec)), Qmargin))
5693 && !EQ (XCAR (spec), Qleft_fringe)
5694 && !EQ (XCAR (spec), Qright_fringe)
5695 && !EQ (XCAR (spec), Qmin_width)
5696 && !NILP (XCAR (spec)))
5697 {
5698 for (; CONSP (spec); spec = XCDR (spec))
5699 {
5700 int rv = handle_single_display_spec (it, XCAR (spec), object,
5701 overlay, position, bufpos,
5702 replacing, frame_window_p,
5703 enable_eval);
5704 if (rv != 0)
5705 {
5706 replacing = rv;
5707
5708
5709 if (!it || STRINGP (object))
5710 break;
5711 }
5712 }
5713 }
5714 else if (VECTORP (spec))
5715 {
5716 ptrdiff_t i;
5717 for (i = 0; i < ASIZE (spec); ++i)
5718 {
5719 int rv = handle_single_display_spec (it, AREF (spec, i), object,
5720 overlay, position, bufpos,
5721 replacing, frame_window_p,
5722 enable_eval);
5723 if (rv != 0)
5724 {
5725 replacing = rv;
5726
5727
5728 if (!it || STRINGP (object))
5729 break;
5730 }
5731 }
5732 }
5733 else
5734 replacing = handle_single_display_spec (it, spec, object, overlay, position,
5735 bufpos, 0, frame_window_p,
5736 enable_eval);
5737 return replacing;
5738 }
5739
5740
5741
5742
5743 static struct text_pos
5744 display_prop_end (struct it *it, Lisp_Object object, struct text_pos start_pos)
5745 {
5746 Lisp_Object end;
5747 struct text_pos end_pos;
5748
5749 end = Fnext_single_char_property_change (make_fixnum (CHARPOS (start_pos)),
5750 Qdisplay, object, Qnil);
5751 CHARPOS (end_pos) = XFIXNAT (end);
5752 if (STRINGP (object))
5753 compute_string_pos (&end_pos, start_pos, it->string);
5754 else
5755 BYTEPOS (end_pos) = CHAR_TO_BYTE (XFIXNAT (end));
5756
5757 return end_pos;
5758 }
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786 static int
5787 handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5788 Lisp_Object overlay, struct text_pos *position,
5789 ptrdiff_t bufpos, int display_replaced,
5790 bool frame_window_p, bool enable_eval_p)
5791 {
5792 Lisp_Object form;
5793 Lisp_Object location, value;
5794 struct text_pos start_pos = *position;
5795 void *itdata = NULL;
5796
5797
5798
5799 form = Qt;
5800 if (CONSP (spec) && EQ (XCAR (spec), Qwhen))
5801 {
5802 spec = XCDR (spec);
5803 if (!CONSP (spec))
5804 return 0;
5805 form = XCAR (spec);
5806 spec = XCDR (spec);
5807 }
5808
5809 if (!NILP (form) && !EQ (form, Qt) && !enable_eval_p)
5810 form = Qnil;
5811 if (!NILP (form) && !EQ (form, Qt))
5812 {
5813 specpdl_ref count = SPECPDL_INDEX ();
5814
5815
5816
5817
5818
5819
5820 if (NILP (object))
5821 XSETBUFFER (object, current_buffer);
5822 specbind (Qobject, object);
5823 specbind (Qposition, make_fixnum (CHARPOS (*position)));
5824 specbind (Qbuffer_position, make_fixnum (bufpos));
5825
5826
5827 itdata = bidi_shelve_cache ();
5828 form = safe_eval (form);
5829 bidi_unshelve_cache (itdata, false);
5830 form = unbind_to (count, form);
5831 }
5832
5833 if (NILP (form))
5834 return 0;
5835
5836
5837 if (CONSP (spec)
5838 && EQ (XCAR (spec), Qheight)
5839 && CONSP (XCDR (spec)))
5840 {
5841 if (it)
5842 {
5843 if (!FRAME_WINDOW_P (it->f))
5844 return 0;
5845
5846 it->font_height = XCAR (XCDR (spec));
5847 if (!NILP (it->font_height))
5848 {
5849 int new_height = -1;
5850
5851 if (CONSP (it->font_height)
5852 && (EQ (XCAR (it->font_height), Qplus)
5853 || EQ (XCAR (it->font_height), Qminus))
5854 && CONSP (XCDR (it->font_height))
5855 && RANGED_FIXNUMP (0, XCAR (XCDR (it->font_height)), INT_MAX))
5856 {
5857
5858 int steps = XFIXNUM (XCAR (XCDR (it->font_height)));
5859 if (EQ (XCAR (it->font_height), Qplus))
5860 steps = - steps;
5861 it->face_id = smaller_face (it->f, it->face_id, steps);
5862 }
5863 else if (FUNCTIONP (it->font_height) && enable_eval_p)
5864 {
5865
5866
5867 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5868 Lisp_Object height;
5869 itdata = bidi_shelve_cache ();
5870 height = safe_call1 (it->font_height,
5871 face->lface[LFACE_HEIGHT_INDEX]);
5872 bidi_unshelve_cache (itdata, false);
5873 if (NUMBERP (height))
5874 new_height = XFLOATINT (height);
5875 }
5876 else if (NUMBERP (it->font_height))
5877 {
5878
5879 struct face *f;
5880
5881 f = FACE_FROM_ID (it->f,
5882 lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID));
5883 new_height = (XFLOATINT (it->font_height)
5884 * XFIXNUM (f->lface[LFACE_HEIGHT_INDEX]));
5885 }
5886 else if (enable_eval_p)
5887 {
5888
5889
5890 specpdl_ref count = SPECPDL_INDEX ();
5891 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5892
5893 specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
5894 itdata = bidi_shelve_cache ();
5895 value = safe_eval (it->font_height);
5896 bidi_unshelve_cache (itdata, false);
5897 value = unbind_to (count, value);
5898
5899 if (NUMBERP (value))
5900 new_height = XFLOATINT (value);
5901 }
5902
5903 if (new_height > 0)
5904 it->face_id = face_with_height (it->f, it->face_id, new_height);
5905 }
5906 }
5907
5908 return 0;
5909 }
5910
5911
5912 if (CONSP (spec)
5913 && EQ (XCAR (spec), Qspace_width)
5914 && CONSP (XCDR (spec)))
5915 {
5916 if (it)
5917 {
5918 if (!FRAME_WINDOW_P (it->f))
5919 return 0;
5920
5921 value = XCAR (XCDR (spec));
5922 if (NUMBERP (value) && XFLOATINT (value) > 0)
5923 it->space_width = value;
5924 }
5925
5926 return 0;
5927 }
5928
5929
5930 if (CONSP (spec)
5931 && EQ (XCAR (spec), Qmin_width)
5932 && CONSP (XCDR (spec))
5933 && CONSP (XCAR (XCDR (spec))))
5934 {
5935 if (it)
5936 display_min_width (it, bufpos, object, XCAR (XCDR (spec)));
5937 return 0;
5938 }
5939
5940
5941 if (CONSP (spec)
5942 && EQ (XCAR (spec), Qslice))
5943 {
5944 Lisp_Object tem;
5945
5946 if (it)
5947 {
5948 if (!FRAME_WINDOW_P (it->f))
5949 return 0;
5950
5951 if (tem = XCDR (spec), CONSP (tem))
5952 {
5953 it->slice.x = XCAR (tem);
5954 if (tem = XCDR (tem), CONSP (tem))
5955 {
5956 it->slice.y = XCAR (tem);
5957 if (tem = XCDR (tem), CONSP (tem))
5958 {
5959 it->slice.width = XCAR (tem);
5960 if (tem = XCDR (tem), CONSP (tem))
5961 it->slice.height = XCAR (tem);
5962 }
5963 }
5964 }
5965 }
5966
5967 return 0;
5968 }
5969
5970
5971 if (CONSP (spec)
5972 && EQ (XCAR (spec), Qraise)
5973 && CONSP (XCDR (spec)))
5974 {
5975 if (it)
5976 {
5977 if (!FRAME_WINDOW_P (it->f))
5978 return 0;
5979
5980 #ifdef HAVE_WINDOW_SYSTEM
5981 value = XCAR (XCDR (spec));
5982 if (NUMBERP (value))
5983 {
5984 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5985 it->voffset = - (XFLOATINT (value)
5986 * (normal_char_height (face->font, -1)));
5987 }
5988 #endif
5989 }
5990
5991 return 0;
5992 }
5993
5994
5995
5996 if (it && it->string_from_display_prop_p)
5997 return 0;
5998
5999
6000
6001 if (it)
6002 {
6003 start_pos = *position;
6004 *position = display_prop_end (it, object, start_pos);
6005
6006
6007
6008
6009
6010
6011
6012 if (!NILP (overlay))
6013 {
6014 ptrdiff_t ovendpos = OVERLAY_END (overlay);
6015
6016
6017
6018
6019
6020
6021
6022 ovendpos = clip_to_bounds (BEGV, ovendpos, ZV);
6023
6024 if (ovendpos > CHARPOS (*position))
6025 SET_TEXT_POS (*position, ovendpos, CHAR_TO_BYTE (ovendpos));
6026 }
6027 }
6028 value = Qnil;
6029
6030
6031
6032 if (it)
6033 it->stop_charpos = position->charpos;
6034
6035
6036
6037 if (CONSP (spec)
6038 && (EQ (XCAR (spec), Qleft_fringe)
6039 || EQ (XCAR (spec), Qright_fringe))
6040 && CONSP (XCDR (spec)))
6041 {
6042 if (it)
6043 {
6044 if (!FRAME_WINDOW_P (it->f))
6045
6046
6047 {
6048
6049
6050
6051
6052 if (it->bidi_p)
6053 {
6054 it->position = *position;
6055 iterate_out_of_display_property (it);
6056 *position = it->position;
6057 }
6058 return 1;
6059 }
6060 }
6061 else if (!frame_window_p)
6062 return 1;
6063
6064 #ifdef HAVE_WINDOW_SYSTEM
6065 value = XCAR (XCDR (spec));
6066 int fringe_bitmap = SYMBOLP (value) ? lookup_fringe_bitmap (value) : 0;
6067 if (! fringe_bitmap)
6068
6069
6070 {
6071 if (it && it->bidi_p)
6072 {
6073 it->position = *position;
6074 iterate_out_of_display_property (it);
6075 *position = it->position;
6076 }
6077 return 1;
6078 }
6079
6080 if (it)
6081 {
6082 int face_id = lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
6083
6084 if (CONSP (XCDR (XCDR (spec))))
6085 {
6086 Lisp_Object face_name = XCAR (XCDR (XCDR (spec)));
6087 int face_id2;
6088
6089
6090
6091 specpdl_ref count1 = SPECPDL_INDEX ();
6092 specbind (Qinhibit_quit, Qt);
6093 face_id2 = lookup_derived_face (it->w, it->f, face_name,
6094 FRINGE_FACE_ID, false);
6095 unbind_to (count1, Qnil);
6096 if (face_id2 >= 0)
6097 face_id = face_id2;
6098 }
6099
6100
6101
6102 push_it (it, position);
6103
6104 it->area = TEXT_AREA;
6105 it->what = IT_IMAGE;
6106 it->image_id = -1;
6107 it->position = start_pos;
6108 it->object = NILP (object) ? it->w->contents : object;
6109 it->method = GET_FROM_IMAGE;
6110 it->from_overlay = Qnil;
6111 it->face_id = face_id;
6112 it->from_disp_prop_p = true;
6113
6114
6115
6116
6117 *position = start_pos;
6118
6119 if (EQ (XCAR (spec), Qleft_fringe))
6120 {
6121 it->left_user_fringe_bitmap = fringe_bitmap;
6122 it->left_user_fringe_face_id = face_id;
6123 }
6124 else
6125 {
6126 it->right_user_fringe_bitmap = fringe_bitmap;
6127 it->right_user_fringe_face_id = face_id;
6128 }
6129 }
6130 #endif
6131 return 1;
6132 }
6133
6134
6135
6136
6137 location = Qunbound;
6138 if (CONSP (spec) && CONSP (XCAR (spec)))
6139 {
6140 Lisp_Object tem;
6141
6142 value = XCDR (spec);
6143 if (CONSP (value))
6144 value = XCAR (value);
6145
6146 tem = XCAR (spec);
6147 if (EQ (XCAR (tem), Qmargin)
6148 && (tem = XCDR (tem),
6149 tem = CONSP (tem) ? XCAR (tem) : Qnil,
6150 (NILP (tem)
6151 || EQ (tem, Qleft_margin)
6152 || EQ (tem, Qright_margin))))
6153 location = tem;
6154 }
6155
6156 if (BASE_EQ (location, Qunbound))
6157 {
6158 location = Qnil;
6159 value = spec;
6160 }
6161
6162
6163
6164
6165
6166
6167
6168
6169 bool valid_p = (STRINGP (value)
6170 #ifdef HAVE_WINDOW_SYSTEM
6171 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
6172 && valid_image_p (value))
6173 #endif
6174 || (CONSP (value) && EQ (XCAR (value), Qspace))
6175 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
6176 && valid_xwidget_spec_p (value)));
6177
6178 if (valid_p && display_replaced == 0)
6179 {
6180 int retval = 1;
6181
6182 if (!it)
6183 {
6184
6185
6186
6187 if (CONSP (value) && EQ (XCAR (value), Qspace) && NILP (location))
6188 retval = 2;
6189 return retval;
6190 }
6191
6192
6193
6194 push_it (it, position);
6195 it->from_overlay = overlay;
6196 it->from_disp_prop_p = true;
6197
6198 if (NILP (location))
6199 it->area = TEXT_AREA;
6200 else if (EQ (location, Qleft_margin))
6201 it->area = LEFT_MARGIN_AREA;
6202 else
6203 it->area = RIGHT_MARGIN_AREA;
6204
6205 if (STRINGP (value))
6206 {
6207 it->string = value;
6208 it->multibyte_p = STRING_MULTIBYTE (it->string);
6209 it->current.overlay_string_index = -1;
6210 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
6211 it->end_charpos = it->string_nchars = SCHARS (it->string);
6212 it->method = GET_FROM_STRING;
6213 it->stop_charpos = 0;
6214 it->prev_stop = 0;
6215 it->base_level_stop = 0;
6216 it->string_from_display_prop_p = true;
6217 it->cmp_it.id = -1;
6218
6219
6220
6221 if (BUFFERP (object))
6222 *position = start_pos;
6223
6224
6225
6226
6227 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
6228 it->paragraph_embedding = it->bidi_it.paragraph_dir;
6229 else
6230 it->paragraph_embedding = L2R;
6231
6232
6233 if (it->bidi_p)
6234 {
6235 it->bidi_it.string.lstring = it->string;
6236 it->bidi_it.string.s = NULL;
6237 it->bidi_it.string.schars = it->end_charpos;
6238 it->bidi_it.string.bufpos = bufpos;
6239 it->bidi_it.string.from_disp_str = true;
6240 it->bidi_it.string.unibyte = !it->multibyte_p;
6241 it->bidi_it.w = it->w;
6242 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6243 }
6244 }
6245 else if (CONSP (value) && EQ (XCAR (value), Qspace))
6246 {
6247 it->method = GET_FROM_STRETCH;
6248 it->object = value;
6249 *position = it->position = start_pos;
6250 retval = 1 + (it->area == TEXT_AREA);
6251 }
6252 else if (valid_xwidget_spec_p (value))
6253 {
6254 it->what = IT_XWIDGET;
6255 it->method = GET_FROM_XWIDGET;
6256 it->position = start_pos;
6257 it->object = NILP (object) ? it->w->contents : object;
6258 *position = start_pos;
6259 it->xwidget = lookup_xwidget (value);
6260 }
6261 #ifdef HAVE_WINDOW_SYSTEM
6262 else
6263 {
6264 specpdl_ref count = SPECPDL_INDEX ();
6265
6266 it->what = IT_IMAGE;
6267
6268
6269
6270 specbind (Qinhibit_quit, Qt);
6271 it->image_id = lookup_image (it->f, value, it->face_id);
6272 unbind_to (count, Qnil);
6273 it->position = start_pos;
6274 it->object = NILP (object) ? it->w->contents : object;
6275 it->method = GET_FROM_IMAGE;
6276
6277
6278
6279
6280 *position = start_pos;
6281 }
6282 #endif
6283
6284 return retval;
6285 }
6286
6287
6288
6289 *position = start_pos;
6290 return 0;
6291 }
6292
6293
6294
6295
6296
6297
6298 bool
6299 display_prop_intangible_p (Lisp_Object prop, Lisp_Object overlay,
6300 ptrdiff_t charpos, ptrdiff_t bytepos)
6301 {
6302 bool frame_window_p = FRAME_WINDOW_P (XFRAME (selected_frame));
6303 struct text_pos position;
6304
6305 SET_TEXT_POS (position, charpos, bytepos);
6306 return (handle_display_spec (NULL, prop, Qnil, overlay,
6307 &position, charpos, frame_window_p)
6308 != 0);
6309 }
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320 static bool
6321 single_display_spec_string_p (Lisp_Object prop, Lisp_Object string)
6322 {
6323 if (EQ (string, prop))
6324 return true;
6325
6326
6327 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
6328 {
6329 prop = XCDR (prop);
6330 if (!CONSP (prop))
6331 return false;
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342 prop = XCDR (prop);
6343 }
6344
6345 if (CONSP (prop))
6346
6347 if (EQ (XCAR (prop), Qmargin))
6348 {
6349 prop = XCDR (prop);
6350 if (!CONSP (prop))
6351 return false;
6352
6353 prop = XCDR (prop);
6354 if (!CONSP (prop))
6355 return false;
6356 }
6357
6358 return EQ (prop, string) || (CONSP (prop) && EQ (XCAR (prop), string));
6359 }
6360
6361
6362
6363
6364 static bool
6365 display_prop_string_p (Lisp_Object prop, Lisp_Object string)
6366 {
6367 if (CONSP (prop)
6368 && !EQ (XCAR (prop), Qwhen)
6369 && !(CONSP (XCAR (prop)) && EQ (Qmargin, XCAR (XCAR (prop)))))
6370 {
6371
6372 while (CONSP (prop))
6373 {
6374 if (single_display_spec_string_p (XCAR (prop), string))
6375 return true;
6376 prop = XCDR (prop);
6377 }
6378 }
6379 else if (VECTORP (prop))
6380 {
6381
6382 ptrdiff_t i;
6383 for (i = 0; i < ASIZE (prop); ++i)
6384 if (single_display_spec_string_p (AREF (prop, i), string))
6385 return true;
6386 }
6387 else
6388 return single_display_spec_string_p (prop, string);
6389
6390 return false;
6391 }
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403 static ptrdiff_t
6404 string_buffer_position_lim (Lisp_Object string,
6405 ptrdiff_t from, ptrdiff_t to, bool back_p)
6406 {
6407 Lisp_Object limit, prop, pos;
6408 bool found = false;
6409
6410 pos = make_fixnum (max (from, BEGV));
6411
6412 if (!back_p)
6413 {
6414 limit = make_fixnum (min (to, ZV));
6415 while (!found && !EQ (pos, limit))
6416 {
6417 prop = Fget_char_property (pos, Qdisplay, Qnil);
6418 if (!NILP (prop) && display_prop_string_p (prop, string))
6419 found = true;
6420 else
6421 pos = Fnext_single_char_property_change (pos, Qdisplay, Qnil,
6422 limit);
6423 }
6424 }
6425 else
6426 {
6427 limit = make_fixnum (max (to, BEGV));
6428 while (!found && !EQ (pos, limit))
6429 {
6430 prop = Fget_char_property (pos, Qdisplay, Qnil);
6431 if (!NILP (prop) && display_prop_string_p (prop, string))
6432 found = true;
6433 else
6434 pos = Fprevious_single_char_property_change (pos, Qdisplay, Qnil,
6435 limit);
6436 }
6437 }
6438
6439 return found ? XFIXNUM (pos) : 0;
6440 }
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451 static ptrdiff_t
6452 string_buffer_position (Lisp_Object string, ptrdiff_t around_charpos)
6453 {
6454 const int MAX_DISTANCE = 1000;
6455 ptrdiff_t forward_limit = min (around_charpos + MAX_DISTANCE, ZV);
6456 ptrdiff_t found = string_buffer_position_lim (string, around_charpos,
6457 forward_limit, false);
6458
6459 if (!found)
6460 {
6461 ptrdiff_t backward_limit = max (around_charpos - MAX_DISTANCE, BEGV);
6462 found = string_buffer_position_lim (string, around_charpos,
6463 backward_limit, true);
6464 }
6465 return found;
6466 }
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477 static enum prop_handled
6478 handle_composition_prop (struct it *it)
6479 {
6480 Lisp_Object prop, string;
6481 ptrdiff_t pos, pos_byte, start, end;
6482
6483 if (STRINGP (it->string))
6484 {
6485 unsigned char *s;
6486
6487 pos = IT_STRING_CHARPOS (*it);
6488 pos_byte = IT_STRING_BYTEPOS (*it);
6489 string = it->string;
6490 s = SDATA (string) + pos_byte;
6491 if (STRING_MULTIBYTE (string))
6492 it->c = STRING_CHAR (s);
6493 else
6494 it->c = *s;
6495 }
6496 else
6497 {
6498 pos = IT_CHARPOS (*it);
6499 pos_byte = IT_BYTEPOS (*it);
6500 string = Qnil;
6501 it->c = FETCH_CHAR (pos_byte);
6502 }
6503
6504
6505
6506
6507 if (find_composition (pos, -1, &start, &end, &prop, string)
6508 && composition_valid_p (start, end, prop)
6509 && (STRINGP (it->string) || (PT <= start || PT >= end)))
6510 {
6511 if (start < pos)
6512
6513
6514
6515 return HANDLED_NORMALLY;
6516 if (start != pos)
6517 {
6518 if (STRINGP (it->string))
6519 pos_byte = string_char_to_byte (it->string, start);
6520 else
6521 pos_byte = CHAR_TO_BYTE (start);
6522 }
6523 it->cmp_it.id = get_composition_id (start, pos_byte, end - start,
6524 prop, string);
6525
6526 if (it->cmp_it.id >= 0)
6527 {
6528 it->cmp_it.ch = -1;
6529 it->cmp_it.nchars = COMPOSITION_LENGTH (prop);
6530 it->cmp_it.nglyphs = -1;
6531 }
6532 }
6533
6534 return HANDLED_NORMALLY;
6535 }
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546 struct overlay_entry
6547 {
6548 Lisp_Object overlay;
6549 Lisp_Object string;
6550 EMACS_INT priority;
6551 bool after_string_p;
6552 };
6553
6554
6555
6556
6557
6558 static enum prop_handled
6559 handle_overlay_change (struct it *it)
6560 {
6561 if (!STRINGP (it->string) && get_overlay_strings (it, 0))
6562 return HANDLED_RECOMPUTE_PROPS;
6563 else
6564 return HANDLED_NORMALLY;
6565 }
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575 static void
6576 next_overlay_string (struct it *it)
6577 {
6578 ++it->current.overlay_string_index;
6579 if (it->current.overlay_string_index == it->n_overlay_strings)
6580 {
6581
6582
6583
6584
6585 it->ellipsis_p = it->stack[it->sp - 1].display_ellipsis_p;
6586 pop_it (it);
6587 eassert (it->sp > 0
6588 || (NILP (it->string)
6589 && it->method == GET_FROM_BUFFER
6590 && it->stop_charpos >= BEGV
6591 && it->stop_charpos <= it->end_charpos));
6592 it->current.overlay_string_index = -1;
6593 it->n_overlay_strings = 0;
6594
6595
6596
6597
6598 if (it->sp > 0 && STRINGP (it->string) && !SCHARS (it->string))
6599 pop_it (it);
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609 if (it->overlay_strings_charpos == IT_CHARPOS (*it))
6610 it->ignore_overlay_strings_at_pos_p = true;
6611
6612
6613
6614
6615 if (NILP (it->string)
6616 && IT_CHARPOS (*it) >= it->end_charpos
6617 && it->overlay_strings_charpos >= it->end_charpos)
6618 it->overlay_strings_at_end_processed_p = true;
6619
6620
6621
6622
6623
6624
6625
6626 it->overlay_strings_charpos = -1;
6627 }
6628 else
6629 {
6630
6631
6632
6633
6634
6635
6636 int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
6637
6638 if (it->current.overlay_string_index && i == 0)
6639 load_overlay_strings (it, it->overlay_strings_charpos);
6640
6641
6642
6643 it->string = it->overlay_strings[i];
6644 it->multibyte_p = STRING_MULTIBYTE (it->string);
6645 SET_TEXT_POS (it->current.string_pos, 0, 0);
6646 it->method = GET_FROM_STRING;
6647 it->stop_charpos = 0;
6648 it->end_charpos = SCHARS (it->string);
6649 if (it->cmp_it.stop_pos >= 0)
6650 it->cmp_it.stop_pos = 0;
6651 it->prev_stop = 0;
6652 it->base_level_stop = 0;
6653
6654
6655 if (it->bidi_p)
6656 {
6657 it->bidi_it.string.lstring = it->string;
6658 it->bidi_it.string.s = NULL;
6659 it->bidi_it.string.schars = SCHARS (it->string);
6660 it->bidi_it.string.bufpos = it->overlay_strings_charpos;
6661 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
6662 it->bidi_it.string.unibyte = !it->multibyte_p;
6663 it->bidi_it.w = it->w;
6664 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6665 }
6666 }
6667
6668 CHECK_IT (it);
6669 }
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688 static int
6689 compare_overlay_entries (const void *e1, const void *e2)
6690 {
6691 struct overlay_entry const *entry1 = e1;
6692 struct overlay_entry const *entry2 = e2;
6693 int result;
6694
6695 if (entry1->after_string_p != entry2->after_string_p)
6696 {
6697
6698
6699 if (EQ (entry1->overlay, entry2->overlay))
6700 result = entry1->after_string_p ? 1 : -1;
6701 else
6702 result = entry1->after_string_p ? -1 : 1;
6703 }
6704 else if (entry1->priority != entry2->priority)
6705 {
6706 if (entry1->after_string_p)
6707
6708 result = entry2->priority < entry1->priority ? -1 : 1;
6709 else
6710
6711 result = entry1->priority < entry2->priority ? -1 : 1;
6712 }
6713 else
6714 result = 0;
6715
6716 return result;
6717 }
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744 static void
6745 load_overlay_strings (struct it *it, ptrdiff_t charpos)
6746 {
6747 ptrdiff_t n = 0;
6748 struct overlay_entry entriesbuf[20];
6749 ptrdiff_t size = ARRAYELTS (entriesbuf);
6750 struct overlay_entry *entries = entriesbuf;
6751 struct itree_node *node;
6752
6753 USE_SAFE_ALLOCA;
6754
6755 if (charpos <= 0)
6756 charpos = IT_CHARPOS (*it);
6757
6758
6759
6760
6761
6762 #define RECORD_OVERLAY_STRING(OVERLAY, STRING, AFTER_P) \
6763 do \
6764 { \
6765 Lisp_Object priority; \
6766 \
6767 if (n == size) \
6768 { \
6769 struct overlay_entry *old = entries; \
6770 SAFE_NALLOCA (entries, 2, size); \
6771 memcpy (entries, old, size * sizeof *entries); \
6772 size *= 2; \
6773 } \
6774 \
6775 entries[n].string = (STRING); \
6776 entries[n].overlay = (OVERLAY); \
6777 priority = Foverlay_get ((OVERLAY), Qpriority); \
6778 entries[n].priority = FIXNUMP (priority) ? XFIXNUM (priority) : 0; \
6779 entries[n].after_string_p = (AFTER_P); \
6780 ++n; \
6781 } \
6782 while (false)
6783
6784
6785
6786 ITREE_FOREACH (node, current_buffer->overlays, charpos - 1, charpos + 1, DESCENDING)
6787 {
6788 Lisp_Object overlay = node->data;
6789 eassert (OVERLAYP (overlay));
6790 ptrdiff_t start = node->begin;
6791 ptrdiff_t end = node->end;
6792
6793
6794
6795 if (end != charpos && start != charpos)
6796 continue;
6797
6798
6799 Lisp_Object window = Foverlay_get (overlay, Qwindow);
6800 if (WINDOWP (window) && XWINDOW (window) != it->w)
6801 continue;
6802
6803
6804
6805
6806 Lisp_Object invisible = Foverlay_get (overlay, Qinvisible);
6807 int invis = TEXT_PROP_MEANS_INVISIBLE (invisible);
6808
6809
6810 Lisp_Object str;
6811 if ((start == charpos || (end == charpos && invis != 0))
6812 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
6813 && SCHARS (str))
6814 RECORD_OVERLAY_STRING (overlay, str, false);
6815
6816
6817 if ((end == charpos || (start == charpos && invis != 0))
6818 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
6819 && SCHARS (str))
6820 RECORD_OVERLAY_STRING (overlay, str, true);
6821 }
6822
6823 #undef RECORD_OVERLAY_STRING
6824
6825
6826 if (n > 1)
6827 qsort (entries, n, sizeof *entries, compare_overlay_entries);
6828
6829
6830 it->n_overlay_strings = n;
6831 it->overlay_strings_charpos = charpos;
6832
6833
6834
6835
6836 ptrdiff_t j = it->current.overlay_string_index;
6837 for (ptrdiff_t i = 0; i < OVERLAY_STRING_CHUNK_SIZE && j < n; i++, j++)
6838 {
6839 it->overlay_strings[i] = entries[j].string;
6840 it->string_overlays[i] = entries[j].overlay;
6841 }
6842
6843 CHECK_IT (it);
6844 SAFE_FREE ();
6845 }
6846
6847
6848
6849
6850
6851
6852 static bool
6853 get_overlay_strings_1 (struct it *it, ptrdiff_t charpos, bool compute_stop_p)
6854 {
6855
6856
6857
6858
6859
6860
6861
6862 it->current.overlay_string_index = 0;
6863 load_overlay_strings (it, charpos);
6864
6865
6866
6867
6868 if (it->n_overlay_strings)
6869 {
6870
6871
6872
6873 if (compute_stop_p)
6874 compute_stop_pos (it);
6875 eassert (it->face_id >= 0);
6876
6877
6878
6879 eassert (!compute_stop_p || it->sp == 0);
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889 if (!(!it->bidi_p
6890 && STRINGP (it->string) && !SCHARS (it->string)))
6891 push_it (it, NULL);
6892
6893
6894
6895 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
6896 it->string = it->overlay_strings[0];
6897 it->from_overlay = Qnil;
6898 it->stop_charpos = 0;
6899 eassert (STRINGP (it->string));
6900 it->end_charpos = SCHARS (it->string);
6901 it->prev_stop = 0;
6902 it->base_level_stop = 0;
6903 it->multibyte_p = STRING_MULTIBYTE (it->string);
6904 it->method = GET_FROM_STRING;
6905 it->from_disp_prop_p = 0;
6906 it->cmp_it.id = -1;
6907
6908
6909
6910 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
6911 it->paragraph_embedding = it->bidi_it.paragraph_dir;
6912 else
6913 it->paragraph_embedding = L2R;
6914
6915
6916 if (it->bidi_p)
6917 {
6918 ptrdiff_t pos = (charpos > 0 ? charpos : IT_CHARPOS (*it));
6919
6920 it->bidi_it.string.lstring = it->string;
6921 it->bidi_it.string.s = NULL;
6922 it->bidi_it.string.schars = SCHARS (it->string);
6923 it->bidi_it.string.bufpos = pos;
6924 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
6925 it->bidi_it.string.unibyte = !it->multibyte_p;
6926 it->bidi_it.w = it->w;
6927 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6928 }
6929 return true;
6930 }
6931
6932 it->current.overlay_string_index = -1;
6933 return false;
6934 }
6935
6936 static bool
6937 get_overlay_strings (struct it *it, ptrdiff_t charpos)
6938 {
6939 it->string = Qnil;
6940 it->method = GET_FROM_BUFFER;
6941
6942 get_overlay_strings_1 (it, charpos, true);
6943
6944 CHECK_IT (it);
6945
6946
6947 return STRINGP (it->string);
6948 }
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962 static void
6963 push_it (struct it *it, struct text_pos *position)
6964 {
6965 struct iterator_stack_entry *p;
6966
6967 eassert (it->sp < IT_STACK_SIZE);
6968 p = it->stack + it->sp;
6969
6970 p->stop_charpos = it->stop_charpos;
6971 p->prev_stop = it->prev_stop;
6972 p->base_level_stop = it->base_level_stop;
6973 p->cmp_it = it->cmp_it;
6974 eassert (it->face_id >= 0);
6975 p->face_id = it->face_id;
6976 p->string = it->string;
6977 p->method = it->method;
6978 p->from_overlay = it->from_overlay;
6979 switch (p->method)
6980 {
6981 case GET_FROM_IMAGE:
6982 p->u.image.object = it->object;
6983 p->u.image.image_id = it->image_id;
6984 p->u.image.slice = it->slice;
6985 break;
6986 case GET_FROM_STRETCH:
6987 p->u.stretch.object = it->object;
6988 break;
6989 case GET_FROM_XWIDGET:
6990 p->u.xwidget.object = it->object;
6991 break;
6992 case GET_FROM_BUFFER:
6993 case GET_FROM_DISPLAY_VECTOR:
6994 case GET_FROM_STRING:
6995 case GET_FROM_C_STRING:
6996 break;
6997 default:
6998 emacs_abort ();
6999 }
7000 p->position = position ? *position : it->position;
7001 p->current = it->current;
7002 p->end_charpos = it->end_charpos;
7003 p->string_nchars = it->string_nchars;
7004 p->area = it->area;
7005 p->multibyte_p = it->multibyte_p;
7006 p->avoid_cursor_p = it->avoid_cursor_p;
7007 p->space_width = it->space_width;
7008 p->font_height = it->font_height;
7009 p->voffset = it->voffset;
7010 p->string_from_display_prop_p = it->string_from_display_prop_p;
7011 p->string_from_prefix_prop_p = it->string_from_prefix_prop_p;
7012 p->display_ellipsis_p = false;
7013 p->line_wrap = it->line_wrap;
7014 p->bidi_p = it->bidi_p;
7015 p->paragraph_embedding = it->paragraph_embedding;
7016 p->from_disp_prop_p = it->from_disp_prop_p;
7017 ++it->sp;
7018
7019
7020 if (it->bidi_p)
7021 bidi_push_it (&it->bidi_it);
7022 }
7023
7024 static void
7025 iterate_out_of_display_property (struct it *it)
7026 {
7027 bool buffer_p = !STRINGP (it->string);
7028 ptrdiff_t eob = (buffer_p ? ZV : it->end_charpos);
7029 ptrdiff_t bob = (buffer_p ? BEGV : 0);
7030
7031 eassert (eob >= CHARPOS (it->position) && CHARPOS (it->position) >= bob);
7032
7033
7034
7035
7036 if (it->bidi_it.first_elt && it->bidi_it.charpos < eob)
7037 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
7038
7039 while (it->bidi_it.charpos >= bob
7040 && it->prev_stop <= it->bidi_it.charpos
7041 && it->bidi_it.charpos < CHARPOS (it->position)
7042 && it->bidi_it.charpos < eob)
7043 bidi_move_to_visually_next (&it->bidi_it);
7044
7045
7046 if (it->bidi_it.charpos > CHARPOS (it->position))
7047 it->prev_stop = CHARPOS (it->position);
7048
7049
7050 if (it->bidi_it.charpos != CHARPOS (it->position))
7051 SET_TEXT_POS (it->position, it->bidi_it.charpos, it->bidi_it.bytepos);
7052 if (buffer_p)
7053 it->current.pos = it->position;
7054 else
7055 it->current.string_pos = it->position;
7056 }
7057
7058
7059
7060
7061
7062 static void
7063 restore_face_box_flags (struct it *it, int prev_face_id)
7064 {
7065 struct face *face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
7066
7067 if (face)
7068 {
7069 struct face *prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
7070
7071 if (!(it->start_of_box_run_p && prev_face && prev_face->box))
7072 it->start_of_box_run_p = (face->box != FACE_NO_BOX
7073 && (prev_face == NULL
7074 || prev_face->box == FACE_NO_BOX));
7075 it->face_box_p = face->box != FACE_NO_BOX;
7076 }
7077 }
7078
7079
7080
7081
7082
7083
7084
7085 static void
7086 pop_it (struct it *it)
7087 {
7088 struct iterator_stack_entry *p;
7089 bool from_display_prop = it->from_disp_prop_p;
7090 ptrdiff_t prev_pos = IT_CHARPOS (*it);
7091 int prev_face_id = it->face_id;
7092
7093 eassert (it->sp > 0);
7094 --it->sp;
7095 p = it->stack + it->sp;
7096 it->stop_charpos = p->stop_charpos;
7097 it->prev_stop = p->prev_stop;
7098 it->base_level_stop = p->base_level_stop;
7099 it->cmp_it = p->cmp_it;
7100 it->face_id = p->face_id;
7101 it->current = p->current;
7102 it->position = p->position;
7103 it->string = p->string;
7104 it->from_overlay = p->from_overlay;
7105 if (NILP (it->string))
7106 SET_TEXT_POS (it->current.string_pos, -1, -1);
7107 it->method = p->method;
7108 switch (it->method)
7109 {
7110 case GET_FROM_IMAGE:
7111 it->image_id = p->u.image.image_id;
7112 it->object = p->u.image.object;
7113 it->slice = p->u.image.slice;
7114 break;
7115 case GET_FROM_XWIDGET:
7116 it->object = p->u.xwidget.object;
7117 break;
7118 case GET_FROM_STRETCH:
7119 it->object = p->u.stretch.object;
7120 break;
7121 case GET_FROM_BUFFER:
7122 {
7123 restore_face_box_flags (it, prev_face_id);
7124 it->object = it->w->contents;
7125 }
7126 break;
7127 case GET_FROM_STRING:
7128 {
7129 restore_face_box_flags (it, prev_face_id);
7130 it->object = it->string;
7131 }
7132 break;
7133 case GET_FROM_DISPLAY_VECTOR:
7134 if (it->s)
7135 it->method = GET_FROM_C_STRING;
7136 else if (STRINGP (it->string))
7137 it->method = GET_FROM_STRING;
7138 else
7139 {
7140 it->method = GET_FROM_BUFFER;
7141 it->object = it->w->contents;
7142 }
7143 break;
7144 case GET_FROM_C_STRING:
7145 break;
7146 default:
7147 emacs_abort ();
7148 }
7149 it->end_charpos = p->end_charpos;
7150 it->string_nchars = p->string_nchars;
7151 it->area = p->area;
7152 it->multibyte_p = p->multibyte_p;
7153 it->avoid_cursor_p = p->avoid_cursor_p;
7154 it->space_width = p->space_width;
7155 it->font_height = p->font_height;
7156 it->voffset = p->voffset;
7157 it->string_from_display_prop_p = p->string_from_display_prop_p;
7158 it->string_from_prefix_prop_p = p->string_from_prefix_prop_p;
7159 it->line_wrap = p->line_wrap;
7160 it->bidi_p = p->bidi_p;
7161 it->paragraph_embedding = p->paragraph_embedding;
7162 it->from_disp_prop_p = p->from_disp_prop_p;
7163 if (it->bidi_p)
7164 {
7165 bidi_pop_it (&it->bidi_it);
7166
7167
7168
7169
7170
7171
7172
7173 if (from_display_prop
7174 && (it->method == GET_FROM_BUFFER || it->method == GET_FROM_STRING))
7175 iterate_out_of_display_property (it);
7176
7177 eassert ((BUFFERP (it->object)
7178 && IT_CHARPOS (*it) == it->bidi_it.charpos
7179 && IT_BYTEPOS (*it) == it->bidi_it.bytepos)
7180 || (STRINGP (it->object)
7181 && IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
7182 && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos)
7183 || (CONSP (it->object) && it->method == GET_FROM_STRETCH)
7184
7185
7186
7187
7188
7189
7190 || it->sp > 0);
7191 }
7192
7193
7194
7195 if (from_display_prop && it->sp == 0 && CHARPOS (it->position) != prev_pos)
7196 it->ignore_overlay_strings_at_pos_p = false;
7197 }
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207 static void
7208 back_to_previous_line_start (struct it *it)
7209 {
7210 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
7211
7212 dec_both (&cp, &bp);
7213 SET_WITH_NARROWED_BEGV (it, IT_CHARPOS (*it),
7214 find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it)),
7215 get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
7216 }
7217
7218
7219
7220
7221
7222 static bool
7223 strings_with_newlines (ptrdiff_t startpos, ptrdiff_t endpos, struct window *w)
7224 {
7225 struct itree_node *node;
7226
7227 ITREE_FOREACH (node, current_buffer->overlays, startpos, endpos, DESCENDING)
7228 {
7229 Lisp_Object overlay = node->data;
7230 eassert (OVERLAYP (overlay));
7231
7232
7233 Lisp_Object window = Foverlay_get (overlay, Qwindow);
7234 if (WINDOWP (window) && XWINDOW (window) != w)
7235 continue;
7236
7237 ptrdiff_t ostart = node->begin;
7238 ptrdiff_t oend = node->end;
7239
7240
7241 if (!((startpos < oend && ostart < endpos)
7242 || (ostart == oend
7243 && (startpos == oend || (endpos == ZV && oend == endpos)))))
7244 continue;
7245
7246 Lisp_Object str;
7247 str = Foverlay_get (overlay, Qbefore_string);
7248 if (STRINGP (str) && SCHARS (str)
7249 && memchr (SDATA (str), '\n', SBYTES (str)))
7250 return true;
7251 str = Foverlay_get (overlay, Qafter_string);
7252 if (STRINGP (str) && SCHARS (str)
7253 && memchr (SDATA (str), '\n', SBYTES (str)))
7254 return true;
7255 }
7256
7257
7258 Lisp_Object cpos = make_fixnum (startpos);
7259 Lisp_Object limpos = make_fixnum (endpos);
7260
7261 while ((cpos = Fnext_single_property_change (cpos, Qdisplay, Qnil, limpos),
7262 !(NILP (cpos) || XFIXNAT (cpos) >= endpos)))
7263 {
7264 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
7265 Lisp_Object string = string_from_display_spec (spec);
7266 if (STRINGP (string)
7267 && memchr (SDATA (string), '\n', SBYTES (string)))
7268 return true;
7269 }
7270
7271 return false;
7272 }
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296 static bool
7297 forward_to_next_line_start (struct it *it, bool *skipped_p,
7298 struct bidi_it *bidi_it_prev)
7299 {
7300 ptrdiff_t old_selective;
7301 bool newline_found_p = false;
7302 int n;
7303 const int MAX_NEWLINE_DISTANCE = 500;
7304
7305
7306
7307 if (it->what == IT_CHARACTER
7308 && it->c == '\n'
7309 && CHARPOS (it->position) == IT_CHARPOS (*it))
7310 {
7311 if (it->bidi_p && bidi_it_prev)
7312 *bidi_it_prev = it->bidi_it;
7313 set_iterator_to_next (it, false);
7314 it->c = 0;
7315 return true;
7316 }
7317
7318
7319
7320
7321
7322 old_selective = it->selective;
7323 it->selective = 0;
7324
7325
7326
7327
7328 for (n = 0;
7329 !newline_found_p && n < MAX_NEWLINE_DISTANCE;
7330 n += !STRINGP (it->string))
7331 {
7332 if (!get_next_display_element (it))
7333 return false;
7334 newline_found_p = it->what == IT_CHARACTER && it->c == '\n';
7335 if (newline_found_p && it->bidi_p && bidi_it_prev)
7336 *bidi_it_prev = it->bidi_it;
7337 set_iterator_to_next (it, false);
7338 }
7339
7340
7341
7342 if (!newline_found_p)
7343 {
7344 ptrdiff_t bytepos, start = IT_CHARPOS (*it);
7345 ptrdiff_t limit = find_newline_no_quit (start, IT_BYTEPOS (*it),
7346 1, &bytepos);
7347 eassert (!STRINGP (it->string));
7348
7349
7350
7351
7352 bool no_strings_with_newlines = it->stop_charpos >= limit;
7353
7354 if (!no_strings_with_newlines)
7355 {
7356 if (!(current_buffer->long_line_optimizations_p
7357 && it->line_wrap == TRUNCATE))
7358 {
7359
7360
7361 Lisp_Object pos =
7362 Fnext_single_property_change (make_fixnum (start),
7363 Qdisplay, Qnil,
7364 make_fixnum (limit));
7365 no_strings_with_newlines =
7366 (NILP (pos) || XFIXNAT (pos) == limit)
7367 && next_overlay_change (start) == ZV;
7368 }
7369 else
7370 {
7371
7372
7373
7374
7375 no_strings_with_newlines =
7376 !strings_with_newlines (start, limit, it->w);
7377 }
7378 }
7379
7380
7381
7382
7383 if (no_strings_with_newlines)
7384 {
7385 if (!it->bidi_p || !bidi_it_prev)
7386 {
7387
7388 IT_CHARPOS (*it) = limit;
7389 IT_BYTEPOS (*it) = bytepos;
7390 }
7391 else
7392 {
7393
7394
7395
7396 struct bidi_it bprev;
7397
7398
7399
7400
7401 if (it->bidi_it.disp_pos < limit)
7402 {
7403 it->bidi_it.disp_pos = limit;
7404 it->bidi_it.disp_prop = 0;
7405 }
7406 do {
7407 bprev = it->bidi_it;
7408 bidi_move_to_visually_next (&it->bidi_it);
7409 } while (it->bidi_it.charpos != limit);
7410 IT_CHARPOS (*it) = limit;
7411 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
7412 if (bidi_it_prev)
7413 *bidi_it_prev = bprev;
7414 }
7415 *skipped_p = newline_found_p = true;
7416 }
7417 else
7418 {
7419
7420 while (!newline_found_p)
7421 {
7422 if (!get_next_display_element (it))
7423 break;
7424 newline_found_p = ITERATOR_AT_END_OF_LINE_P (it);
7425 if (newline_found_p && it->bidi_p && bidi_it_prev)
7426 *bidi_it_prev = it->bidi_it;
7427 set_iterator_to_next (it, false);
7428 }
7429 }
7430 }
7431
7432 it->selective = old_selective;
7433 return newline_found_p;
7434 }
7435
7436
7437
7438
7439
7440
7441
7442 static void
7443 back_to_previous_visible_line_start (struct it *it)
7444 {
7445 while (IT_CHARPOS (*it) > BEGV)
7446 {
7447 back_to_previous_line_start (it);
7448
7449 if (IT_CHARPOS (*it) <= BEGV)
7450 break;
7451
7452
7453
7454 if (it->selective > 0
7455 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
7456 it->selective))
7457 continue;
7458
7459
7460 {
7461 Lisp_Object prop;
7462 prop = Fget_char_property (make_fixnum (IT_CHARPOS (*it) - 1),
7463 Qinvisible, it->window);
7464 if (TEXT_PROP_MEANS_INVISIBLE (prop) != 0)
7465 continue;
7466 }
7467
7468 if (IT_CHARPOS (*it) <= BEGV)
7469 break;
7470
7471 {
7472 struct it it2;
7473 void *it2data = NULL;
7474 ptrdiff_t pos;
7475 ptrdiff_t beg, end;
7476 Lisp_Object val, overlay;
7477
7478 SAVE_IT (it2, *it, it2data);
7479
7480
7481 if (find_composition (IT_CHARPOS (*it), -1, &beg, &end, &val, Qnil)
7482 && beg < IT_CHARPOS (*it))
7483 goto replaced;
7484
7485
7486
7487 pos = --IT_CHARPOS (it2);
7488 --IT_BYTEPOS (it2);
7489 it2.sp = 0;
7490 bidi_unshelve_cache (NULL, false);
7491 it2.string_from_display_prop_p = false;
7492 it2.from_disp_prop_p = false;
7493 if (handle_display_prop (&it2) == HANDLED_RETURN
7494 && !NILP (val = get_char_property_and_overlay
7495 (make_fixnum (pos), Qdisplay, Qnil, &overlay))
7496 && (OVERLAYP (overlay)
7497 ? (beg = OVERLAY_START (overlay))
7498 : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil)))
7499 {
7500 RESTORE_IT (it, it, it2data);
7501 goto replaced;
7502 }
7503
7504
7505 RESTORE_IT (it, it, it2data);
7506 break;
7507
7508 replaced:
7509 if (beg < BEGV)
7510 beg = BEGV;
7511 IT_CHARPOS (*it) = beg;
7512 IT_BYTEPOS (*it) = buf_charpos_to_bytepos (current_buffer, beg);
7513 }
7514 }
7515
7516 it->continuation_lines_width = 0;
7517
7518 eassert (IT_CHARPOS (*it) >= BEGV);
7519 eassert (it->medium_narrowing_begv > 0
7520 || IT_CHARPOS (*it) == BEGV
7521 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
7522 CHECK_IT (it);
7523 }
7524
7525
7526
7527
7528
7529
7530
7531 void
7532 reseat_at_previous_visible_line_start (struct it *it)
7533 {
7534 back_to_previous_visible_line_start (it);
7535 reseat (it, it->current.pos, true);
7536 CHECK_IT (it);
7537 }
7538
7539
7540
7541
7542
7543
7544
7545
7546
7547 static void
7548 reseat_at_next_visible_line_start (struct it *it, bool on_newline_p)
7549 {
7550 bool skipped_p = false;
7551 struct bidi_it bidi_it_prev;
7552 bool newline_found_p
7553 = forward_to_next_line_start (it, &skipped_p,
7554 on_newline_p ? &bidi_it_prev : NULL);
7555
7556
7557
7558 if (it->selective > 0)
7559 while (IT_CHARPOS (*it) < ZV
7560 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
7561 it->selective))
7562 {
7563 eassert (IT_BYTEPOS (*it) == BEGV
7564 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
7565 newline_found_p =
7566 forward_to_next_line_start (it, &skipped_p,
7567 on_newline_p ? &bidi_it_prev : NULL);
7568 }
7569
7570
7571 if (on_newline_p && newline_found_p)
7572 {
7573 if (STRINGP (it->string))
7574 {
7575 if (IT_STRING_CHARPOS (*it) > 0)
7576 {
7577 if (!it->bidi_p)
7578 {
7579 --IT_STRING_CHARPOS (*it);
7580 --IT_STRING_BYTEPOS (*it);
7581 }
7582 else
7583 {
7584
7585
7586
7587 it->bidi_it = bidi_it_prev;
7588 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
7589 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
7590 }
7591 }
7592 }
7593 else if (IT_CHARPOS (*it) > BEGV)
7594 {
7595 if (!it->bidi_p)
7596 {
7597 --IT_CHARPOS (*it);
7598 --IT_BYTEPOS (*it);
7599 }
7600 else
7601 {
7602
7603
7604 it->bidi_it = bidi_it_prev;
7605 IT_CHARPOS (*it) = it->bidi_it.charpos;
7606 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
7607 }
7608 reseat (it, it->current.pos, false);
7609 }
7610 }
7611 else if (skipped_p)
7612 reseat (it, it->current.pos, false);
7613
7614 CHECK_IT (it);
7615 }
7616
7617
7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628 static void
7629 reseat (struct it *it, struct text_pos pos, bool force_p)
7630 {
7631 ptrdiff_t original_pos = IT_CHARPOS (*it);
7632
7633 reseat_1 (it, pos, false);
7634
7635 if (current_buffer->long_line_optimizations_p)
7636 {
7637 if (!it->medium_narrowing_begv)
7638 {
7639 it->medium_narrowing_begv
7640 = get_medium_narrowing_begv (it->w, window_point (it->w));
7641 it->medium_narrowing_zv
7642 = get_medium_narrowing_zv (it->w, window_point (it->w));
7643 it->large_narrowing_begv
7644 = get_large_narrowing_begv (window_point (it->w));
7645 it->large_narrowing_zv
7646 = get_large_narrowing_zv (window_point (it->w));
7647 }
7648 else if ((pos.charpos < it->medium_narrowing_begv
7649 || pos.charpos > it->medium_narrowing_zv)
7650 && (!redisplaying_p || it->line_wrap == TRUNCATE))
7651 {
7652 it->medium_narrowing_begv
7653 = get_medium_narrowing_begv (it->w, pos.charpos);
7654 it->medium_narrowing_zv
7655 = get_medium_narrowing_zv (it->w, pos.charpos);
7656 it->large_narrowing_begv
7657 = get_large_narrowing_begv (window_point (it->w));
7658 it->large_narrowing_zv
7659 = get_large_narrowing_zv (window_point (it->w));
7660 }
7661 }
7662
7663
7664
7665 if (force_p
7666 || CHARPOS (pos) > it->stop_charpos
7667 || CHARPOS (pos) < original_pos)
7668 {
7669 if (it->bidi_p)
7670 {
7671
7672
7673
7674
7675
7676
7677
7678
7679
7680
7681 if (CHARPOS (pos) != it->prev_stop)
7682 it->prev_stop = CHARPOS (pos);
7683 if (CHARPOS (pos) < it->base_level_stop)
7684 it->base_level_stop = 0;
7685 handle_stop (it);
7686 }
7687 else
7688 {
7689 handle_stop (it);
7690 it->prev_stop = it->base_level_stop = 0;
7691 }
7692
7693 }
7694
7695 CHECK_IT (it);
7696 }
7697
7698
7699
7700
7701
7702 static void
7703 reseat_1 (struct it *it, struct text_pos pos, bool set_stop_p)
7704 {
7705
7706 eassert (it->s == NULL);
7707
7708
7709 eassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
7710
7711 it->current.pos = it->position = pos;
7712 it->end_charpos = ZV;
7713 it->dpvec = NULL;
7714 it->current.dpvec_index = -1;
7715 it->current.overlay_string_index = -1;
7716 IT_STRING_CHARPOS (*it) = -1;
7717 IT_STRING_BYTEPOS (*it) = -1;
7718 it->string = Qnil;
7719 it->method = GET_FROM_BUFFER;
7720 it->object = it->w->contents;
7721 it->area = TEXT_AREA;
7722 it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
7723 it->sp = 0;
7724 it->string_from_display_prop_p = false;
7725 it->string_from_prefix_prop_p = false;
7726
7727 it->from_disp_prop_p = false;
7728 it->face_before_selective_p = false;
7729 if (it->bidi_p)
7730 {
7731 bidi_init_it (IT_CHARPOS (*it), IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
7732 &it->bidi_it);
7733 bidi_unshelve_cache (NULL, false);
7734 it->bidi_it.paragraph_dir = NEUTRAL_DIR;
7735 it->bidi_it.string.s = NULL;
7736 it->bidi_it.string.lstring = Qnil;
7737 it->bidi_it.string.bufpos = 0;
7738 it->bidi_it.string.from_disp_str = false;
7739 it->bidi_it.string.unibyte = false;
7740 it->bidi_it.w = it->w;
7741 }
7742
7743 if (set_stop_p)
7744 {
7745 it->stop_charpos = CHARPOS (pos);
7746 it->base_level_stop = CHARPOS (pos);
7747 }
7748
7749 it->cmp_it.id = -1;
7750 it->min_width_property = Qnil;
7751 }
7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772 static void
7773 reseat_to_string (struct it *it, const char *s, Lisp_Object string,
7774 ptrdiff_t charpos, ptrdiff_t precision, int field_width,
7775 int multibyte)
7776 {
7777
7778 it->stop_charpos = -1;
7779
7780
7781 memset (&it->current, 0, sizeof it->current);
7782 it->current.overlay_string_index = -1;
7783 it->current.dpvec_index = -1;
7784 eassert (charpos >= 0);
7785
7786
7787
7788 if (multibyte >= 0)
7789 it->multibyte_p = multibyte > 0;
7790
7791
7792
7793
7794
7795 it->bidi_p =
7796 !redisplay__inhibit_bidi
7797 && !NILP (BVAR (&buffer_defaults, bidi_display_reordering));
7798
7799 if (s == NULL)
7800 {
7801 eassert (STRINGP (string));
7802 it->string = string;
7803 it->s = NULL;
7804 it->end_charpos = it->string_nchars = SCHARS (string);
7805 it->method = GET_FROM_STRING;
7806 it->current.string_pos = string_pos (charpos, string);
7807
7808 if (it->bidi_p)
7809 {
7810 it->bidi_it.string.lstring = string;
7811 it->bidi_it.string.s = NULL;
7812 it->bidi_it.string.schars = it->end_charpos;
7813 it->bidi_it.string.bufpos = 0;
7814 it->bidi_it.string.from_disp_str = false;
7815 it->bidi_it.string.unibyte = !it->multibyte_p;
7816 it->bidi_it.w = it->w;
7817 bidi_init_it (charpos, IT_STRING_BYTEPOS (*it),
7818 FRAME_WINDOW_P (it->f), &it->bidi_it);
7819 }
7820 }
7821 else
7822 {
7823 it->s = (const unsigned char *) s;
7824 it->string = Qnil;
7825
7826
7827
7828 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
7829 if (it->multibyte_p)
7830 {
7831 it->current.pos = c_string_pos (charpos, s, true);
7832 it->end_charpos = it->string_nchars = number_of_chars (s, true);
7833 }
7834 else
7835 {
7836 IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos;
7837 it->end_charpos = it->string_nchars = strlen (s);
7838 }
7839
7840 if (it->bidi_p)
7841 {
7842 it->bidi_it.string.lstring = Qnil;
7843 it->bidi_it.string.s = (const unsigned char *) s;
7844 it->bidi_it.string.schars = it->end_charpos;
7845 it->bidi_it.string.bufpos = 0;
7846 it->bidi_it.string.from_disp_str = false;
7847 it->bidi_it.string.unibyte = !it->multibyte_p;
7848 it->bidi_it.w = it->w;
7849 bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
7850 &it->bidi_it);
7851 }
7852 it->method = GET_FROM_C_STRING;
7853 }
7854
7855
7856
7857 if (precision > 0 && it->end_charpos - charpos > precision)
7858 {
7859 it->end_charpos = it->string_nchars = charpos + precision;
7860 if (it->bidi_p)
7861 it->bidi_it.string.schars = it->end_charpos;
7862 }
7863
7864
7865
7866
7867
7868 if (field_width < 0)
7869 field_width = DISP_INFINITY;
7870
7871
7872
7873 if (field_width > it->end_charpos - charpos)
7874 it->end_charpos = charpos + field_width;
7875
7876
7877 if (DISP_TABLE_P (Vstandard_display_table))
7878 it->dp = XCHAR_TABLE (Vstandard_display_table);
7879
7880 it->stop_charpos = charpos;
7881 it->prev_stop = charpos;
7882 it->base_level_stop = 0;
7883 if (it->bidi_p)
7884 {
7885 it->bidi_it.first_elt = true;
7886 it->bidi_it.paragraph_dir = NEUTRAL_DIR;
7887 it->bidi_it.disp_pos = -1;
7888 }
7889 if (s == NULL && it->multibyte_p)
7890 {
7891 ptrdiff_t endpos = SCHARS (it->string);
7892 if (endpos > it->end_charpos)
7893 endpos = it->end_charpos;
7894 composition_compute_stop_pos (&it->cmp_it, charpos, -1, endpos,
7895 it->string, true);
7896 }
7897 CHECK_IT (it);
7898 }
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908 typedef bool (*next_element_function) (struct it *);
7909
7910 static next_element_function const get_next_element[NUM_IT_METHODS] =
7911 {
7912 next_element_from_buffer,
7913 next_element_from_display_vector,
7914 next_element_from_string,
7915 next_element_from_c_string,
7916 next_element_from_image,
7917 next_element_from_stretch,
7918 next_element_from_xwidget,
7919 };
7920
7921 #define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it)
7922
7923
7924
7925
7926
7927
7928
7929
7930
7931
7932 #define CHAR_COMPOSED_P(IT,CHARPOS,BYTEPOS,END_CHARPOS) \
7933 ((IT)->cmp_it.id >= 0 \
7934 || ((IT)->cmp_it.stop_pos == (CHARPOS) \
7935 && composition_reseat_it (&(IT)->cmp_it, CHARPOS, BYTEPOS, \
7936 END_CHARPOS, (IT)->w, \
7937 (IT)->bidi_p \
7938 ? (IT)->bidi_it.resolved_level \
7939 : -1, \
7940 FACE_FROM_ID_OR_NULL ((IT)->f, \
7941 (IT)->face_id), \
7942 (IT)->string)))
7943
7944
7945
7946
7947
7948
7949
7950
7951
7952 Lisp_Object
7953 lookup_glyphless_char_display (int c, struct it *it)
7954 {
7955 Lisp_Object glyphless_method = Qnil;
7956
7957 if (CHAR_TABLE_P (Vglyphless_char_display)
7958 && CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display)) >= 1)
7959 {
7960 if (c >= 0)
7961 glyphless_method = CHAR_TABLE_REF (Vglyphless_char_display, c);
7962 else
7963 glyphless_method = XCHAR_TABLE (Vglyphless_char_display)->extras[0];
7964
7965 if (CONSP (glyphless_method))
7966 glyphless_method = FRAME_WINDOW_P (it->f)
7967 ? XCAR (glyphless_method)
7968 : XCDR (glyphless_method);
7969 }
7970
7971 retry:
7972 if (NILP (glyphless_method))
7973 {
7974 if (c >= 0)
7975
7976 return Qnil;
7977
7978 glyphless_method = Qempty_box;
7979 }
7980 if (EQ (glyphless_method, Qzero_width))
7981 {
7982 if (c >= 0)
7983 return glyphless_method;
7984
7985 glyphless_method = Qempty_box;
7986 }
7987 if (EQ (glyphless_method, Qthin_space))
7988 it->glyphless_method = GLYPHLESS_DISPLAY_THIN_SPACE;
7989 else if (EQ (glyphless_method, Qempty_box))
7990 it->glyphless_method = GLYPHLESS_DISPLAY_EMPTY_BOX;
7991 else if (EQ (glyphless_method, Qhex_code))
7992 it->glyphless_method = GLYPHLESS_DISPLAY_HEX_CODE;
7993 else if (STRINGP (glyphless_method))
7994 it->glyphless_method = GLYPHLESS_DISPLAY_ACRONYM;
7995 else
7996 {
7997
7998 glyphless_method = Qnil;
7999 goto retry;
8000 }
8001 it->what = IT_GLYPHLESS;
8002 return glyphless_method;
8003 }
8004
8005
8006
8007 static struct frame *last_escape_glyph_frame = NULL;
8008 static int last_escape_glyph_face_id = (1 << FACE_ID_BITS);
8009 static int last_escape_glyph_merged_face_id = 0;
8010
8011 static int
8012 merge_escape_glyph_face (struct it *it)
8013 {
8014 int face_id;
8015
8016 if (it->f == last_escape_glyph_frame
8017 && it->face_id == last_escape_glyph_face_id)
8018 face_id = last_escape_glyph_merged_face_id;
8019 else
8020 {
8021
8022 face_id = merge_faces (it->w, Qescape_glyph, 0, it->face_id);
8023 last_escape_glyph_frame = it->f;
8024 last_escape_glyph_face_id = it->face_id;
8025 last_escape_glyph_merged_face_id = face_id;
8026 }
8027 return face_id;
8028 }
8029
8030
8031
8032 static struct frame *last_glyphless_glyph_frame = NULL;
8033 static int last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
8034 static int last_glyphless_glyph_merged_face_id = 0;
8035
8036 int
8037 merge_glyphless_glyph_face (struct it *it)
8038 {
8039 int face_id;
8040
8041 if (it->f == last_glyphless_glyph_frame
8042 && it->face_id == last_glyphless_glyph_face_id)
8043 face_id = last_glyphless_glyph_merged_face_id;
8044 else
8045 {
8046
8047 face_id = merge_faces (it->w, Qglyphless_char, 0, it->face_id);
8048 last_glyphless_glyph_frame = it->f;
8049 last_glyphless_glyph_face_id = it->face_id;
8050 last_glyphless_glyph_merged_face_id = face_id;
8051 }
8052 return face_id;
8053 }
8054
8055
8056
8057
8058 void
8059 forget_escape_and_glyphless_faces (void)
8060 {
8061 last_escape_glyph_frame = NULL;
8062 last_escape_glyph_face_id = (1 << FACE_ID_BITS);
8063 last_glyphless_glyph_frame = NULL;
8064 last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
8065 }
8066
8067
8068
8069
8070
8071 static bool
8072 get_next_display_element (struct it *it)
8073 {
8074
8075
8076
8077
8078 bool success_p;
8079
8080 get_next:
8081 success_p = GET_NEXT_DISPLAY_ELEMENT (it);
8082
8083 if (it->what == IT_CHARACTER)
8084 {
8085
8086
8087
8088
8089
8090 if (it->bidi_p && it->bidi_it.type == STRONG_R
8091 && !inhibit_bidi_mirroring)
8092 it->c = bidi_mirror_char (it->c);
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102 if (success_p && it->dpvec == NULL)
8103 {
8104 Lisp_Object dv;
8105 struct charset *unibyte = CHARSET_FROM_ID (charset_unibyte);
8106 bool nonascii_space_p = false;
8107 bool nonascii_hyphen_p = false;
8108 int c = it->c;
8109
8110 if (! it->multibyte_p && ! ASCII_CHAR_P (c))
8111 {
8112 eassert (SINGLE_BYTE_CHAR_P (c));
8113 if (unibyte_display_via_language_environment)
8114 {
8115 c = DECODE_CHAR (unibyte, c);
8116 if (c < 0)
8117 c = BYTE8_TO_CHAR (it->c);
8118 }
8119 else
8120 c = BYTE8_TO_CHAR (it->c);
8121 }
8122
8123 if (it->dp
8124 && (dv = DISP_CHAR_VECTOR (it->dp, c),
8125 VECTORP (dv)))
8126 {
8127 struct Lisp_Vector *v = XVECTOR (dv);
8128
8129
8130
8131
8132 if (v->header.size)
8133 {
8134 it->dpvec_char_len = it->len;
8135 it->dpvec = v->contents;
8136 it->dpend = v->contents + v->header.size;
8137 it->current.dpvec_index = 0;
8138 it->dpvec_face_id = -1;
8139 it->saved_face_id = it->face_id;
8140 it->method = GET_FROM_DISPLAY_VECTOR;
8141 it->ellipsis_p = false;
8142 }
8143 else
8144 {
8145 set_iterator_to_next (it, false);
8146 }
8147 goto get_next;
8148 }
8149
8150 if (! NILP (lookup_glyphless_char_display (c, it)))
8151 {
8152 if (it->what == IT_GLYPHLESS)
8153 goto done;
8154
8155 set_iterator_to_next (it, false);
8156 goto get_next;
8157 }
8158
8159
8160
8161 if (! ASCII_CHAR_P (c) && ! NILP (Vnobreak_char_display))
8162 {
8163 if (blankp (c))
8164 nonascii_space_p = true;
8165 else if (c == SOFT_HYPHEN || c == HYPHEN
8166 || c == NON_BREAKING_HYPHEN)
8167 nonascii_hyphen_p = true;
8168 }
8169
8170
8171
8172
8173
8174
8175
8176
8177
8178
8179
8180
8181 if (((c < ' ' || c == 127)
8182 ? (it->area != TEXT_AREA
8183
8184 || (c != '\t'
8185 && it->glyph_row
8186 && (it->glyph_row->mode_line_p || it->avoid_cursor_p))
8187 || (c != '\n' && c != '\t'))
8188 : (nonascii_space_p
8189 || nonascii_hyphen_p
8190 || CHAR_BYTE8_P (c)
8191 || ! CHAR_PRINTABLE_P (c))))
8192 {
8193
8194
8195
8196
8197
8198
8199 Lisp_Object gc;
8200 int ctl_len;
8201 int face_id;
8202 int lface_id = 0;
8203 int escape_glyph;
8204
8205
8206
8207 if (ASCII_CHAR_P (c) && it->ctl_arrow_p)
8208 {
8209 int g;
8210
8211 g = '^';
8212
8213 if (it->dp
8214 && (gc = DISP_CTRL_GLYPH (it->dp), GLYPH_CODE_P (gc)))
8215 {
8216 g = GLYPH_CODE_CHAR (gc);
8217 lface_id = GLYPH_CODE_FACE (gc);
8218 }
8219
8220 face_id = (lface_id
8221 ? merge_faces (it->w, Qt, lface_id, it->face_id)
8222 : merge_escape_glyph_face (it));
8223
8224 XSETINT (it->ctl_chars[0], g);
8225 XSETINT (it->ctl_chars[1], c ^ 0100);
8226 ctl_len = 2;
8227 goto display_control;
8228 }
8229
8230
8231
8232
8233 if (nonascii_space_p && EQ (Vnobreak_char_display, Qt))
8234 {
8235
8236 face_id = merge_faces (it->w, Qnobreak_space, 0,
8237 it->face_id);
8238 XSETINT (it->ctl_chars[0],
8239 nobreak_char_ascii_display ? ' ' : it->c);
8240 ctl_len = 1;
8241 goto display_control;
8242 }
8243
8244
8245
8246
8247 if (nonascii_hyphen_p && EQ (Vnobreak_char_display, Qt))
8248 {
8249
8250 face_id = merge_faces (it->w, Qnobreak_hyphen, 0,
8251 it->face_id);
8252 XSETINT (it->ctl_chars[0],
8253 nobreak_char_ascii_display ? '-' : it->c);
8254 ctl_len = 1;
8255 goto display_control;
8256 }
8257
8258
8259
8260
8261 escape_glyph = '\\';
8262
8263 if (it->dp
8264 && (gc = DISP_ESCAPE_GLYPH (it->dp), GLYPH_CODE_P (gc)))
8265 {
8266 escape_glyph = GLYPH_CODE_CHAR (gc);
8267 lface_id = GLYPH_CODE_FACE (gc);
8268 }
8269
8270 face_id = (lface_id
8271 ? merge_faces (it->w, Qt, lface_id, it->face_id)
8272 : merge_escape_glyph_face (it));
8273
8274
8275
8276 if (nonascii_space_p || nonascii_hyphen_p)
8277 {
8278 XSETINT (it->ctl_chars[0], escape_glyph);
8279 XSETINT (it->ctl_chars[1], nonascii_space_p ? ' ' : '-');
8280 ctl_len = 2;
8281 goto display_control;
8282 }
8283
8284 {
8285 char str[10];
8286 int len, i;
8287
8288 if (CHAR_BYTE8_P (c))
8289
8290 c = CHAR_TO_BYTE8 (c);
8291 const char *format_string = display_raw_bytes_as_hex
8292 ? "x%02x"
8293 : "%03o";
8294 len = sprintf (str, format_string, c + 0u);
8295
8296 XSETINT (it->ctl_chars[0], escape_glyph);
8297 for (i = 0; i < len; i++)
8298 XSETINT (it->ctl_chars[i + 1], str[i]);
8299 ctl_len = len + 1;
8300 }
8301
8302 display_control:
8303
8304 it->dpvec_char_len = it->len;
8305 it->dpvec = it->ctl_chars;
8306 it->dpend = it->dpvec + ctl_len;
8307 it->current.dpvec_index = 0;
8308 it->dpvec_face_id = face_id;
8309 it->saved_face_id = it->face_id;
8310 it->method = GET_FROM_DISPLAY_VECTOR;
8311 it->ellipsis_p = false;
8312 goto get_next;
8313 }
8314 it->char_to_display = c;
8315 }
8316 else if (success_p)
8317 {
8318 it->char_to_display = it->c;
8319 }
8320 }
8321
8322 #ifdef HAVE_WINDOW_SYSTEM
8323
8324
8325 if ((it->what == IT_CHARACTER || it->what == IT_COMPOSITION)
8326 && it->multibyte_p
8327 && success_p
8328 && FRAME_WINDOW_P (it->f))
8329 {
8330 struct face *face = FACE_FROM_ID (it->f, it->face_id);
8331
8332 if (it->what == IT_COMPOSITION && it->cmp_it.ch >= 0)
8333 {
8334
8335 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
8336
8337 it->face_id = face_for_font (it->f, LGSTRING_FONT (gstring), face);
8338 }
8339 else
8340 {
8341 ptrdiff_t pos = (it->s ? -1
8342 : STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
8343 : IT_CHARPOS (*it));
8344 int c;
8345
8346 if (it->what == IT_CHARACTER)
8347 c = it->char_to_display;
8348 else
8349 {
8350 struct composition *cmp = composition_table[it->cmp_it.id];
8351 int i;
8352
8353 c = ' ';
8354 for (i = 0; i < cmp->glyph_len; i++)
8355
8356
8357 if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t')
8358 break;
8359 }
8360 it->face_id = FACE_FOR_CHAR (it->f, face, c, pos, it->string);
8361 }
8362 }
8363 #endif
8364
8365 done:
8366
8367
8368 if (it->face_box_p
8369 && it->s == NULL)
8370 {
8371 if (it->method == GET_FROM_STRING && it->sp)
8372 {
8373 int face_id = underlying_face_id (it);
8374 struct face *face = FACE_FROM_ID_OR_NULL (it->f, face_id);
8375
8376 if (face)
8377 {
8378 if (face->box == FACE_NO_BOX)
8379 {
8380
8381
8382 int string_face_id = face_after_it_pos (it);
8383 if (FACE_FROM_ID (it->f, string_face_id)->box == FACE_NO_BOX)
8384 it->end_of_box_run_p = true;
8385 }
8386
8387
8388
8389 else if (((IT_STRING_CHARPOS (*it) >= SCHARS (it->string) - 1)
8390
8391
8392
8393 || (it->what == IT_COMPOSITION
8394 && (IT_STRING_CHARPOS (*it) + it->cmp_it.nchars
8395 >= SCHARS (it->string))))
8396
8397
8398 && ((it->current.overlay_string_index >= 0
8399 && (it->current.overlay_string_index
8400 == it->n_overlay_strings - 1))
8401
8402 || it->from_disp_prop_p))
8403 {
8404 ptrdiff_t ignore;
8405 int next_face_id;
8406 bool text_from_string = false;
8407
8408
8409 struct text_pos pos = it->current.pos;
8410
8411
8412
8413
8414
8415
8416
8417
8418
8419
8420
8421 if (it->from_disp_prop_p)
8422 {
8423 int stackp = it->sp - 1;
8424
8425
8426 while (stackp >= 0
8427 && STRINGP ((it->stack + stackp)->string))
8428 stackp--;
8429 if (stackp < 0)
8430 {
8431
8432
8433
8434
8435
8436
8437 text_from_string = true;
8438 pos = it->stack[it->sp - 1].position;
8439 }
8440 else
8441 pos = (it->stack + stackp)->position;
8442 }
8443 else
8444 INC_TEXT_POS (pos, it->multibyte_p);
8445
8446 if (text_from_string)
8447 {
8448 Lisp_Object base_string = it->stack[it->sp - 1].string;
8449
8450 if (CHARPOS (pos) >= SCHARS (base_string) - 1)
8451 it->end_of_box_run_p = true;
8452 else
8453 {
8454 next_face_id
8455 = face_at_string_position (it->w, base_string,
8456 CHARPOS (pos), 0,
8457 &ignore, face_id,
8458 false, 0);
8459 if (FACE_FROM_ID (it->f, next_face_id)->box
8460 == FACE_NO_BOX)
8461 it->end_of_box_run_p = true;
8462 }
8463 }
8464 else if (CHARPOS (pos) >= ZV)
8465 it->end_of_box_run_p = true;
8466 else
8467 {
8468 next_face_id =
8469 face_at_buffer_position (it->w, CHARPOS (pos),
8470 &ignore,
8471 CHARPOS (pos)
8472 + TEXT_PROP_DISTANCE_LIMIT,
8473 false, -1, 0);
8474 if (FACE_FROM_ID (it->f, next_face_id)->box
8475 == FACE_NO_BOX)
8476 it->end_of_box_run_p = true;
8477 }
8478 }
8479 }
8480 }
8481
8482
8483 else if (it->method != GET_FROM_DISPLAY_VECTOR)
8484 {
8485 int face_id = face_after_it_pos (it);
8486 if (face_id != it->face_id
8487 && FACE_FROM_ID (it->f, face_id)->box == FACE_NO_BOX)
8488 it->end_of_box_run_p = true;
8489 }
8490 }
8491
8492
8493
8494
8495
8496 if (!success_p && it->sp > 0)
8497 {
8498 set_iterator_to_next (it, false);
8499 success_p = get_next_display_element (it);
8500 }
8501
8502
8503 return success_p;
8504 }
8505
8506
8507
8508
8509
8510
8511
8512
8513
8514
8515
8516
8517
8518
8519
8520
8521
8522 void
8523 set_iterator_to_next (struct it *it, bool reseat_p)
8524 {
8525
8526 if (max_redisplay_ticks > 0)
8527 update_redisplay_ticks (1, it->w);
8528
8529 switch (it->method)
8530 {
8531 case GET_FROM_BUFFER:
8532
8533
8534
8535 if (ITERATOR_AT_END_OF_LINE_P (it) && reseat_p)
8536 reseat_at_next_visible_line_start (it, false);
8537 else if (it->cmp_it.id >= 0)
8538 {
8539
8540 if (! it->bidi_p)
8541 {
8542 IT_CHARPOS (*it) += it->cmp_it.nchars;
8543 IT_BYTEPOS (*it) += it->cmp_it.nbytes;
8544 }
8545 else
8546 {
8547 int i;
8548
8549
8550
8551
8552 for (i = 0; i < it->cmp_it.nchars; i++)
8553 bidi_move_to_visually_next (&it->bidi_it);
8554 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8555 IT_CHARPOS (*it) = it->bidi_it.charpos;
8556 }
8557
8558 if ((! it->bidi_p || ! it->cmp_it.reversed_p)
8559 && it->cmp_it.to < it->cmp_it.nglyphs)
8560 {
8561
8562
8563 it->cmp_it.from = it->cmp_it.to;
8564 }
8565 else if ((it->bidi_p && it->cmp_it.reversed_p)
8566 && it->cmp_it.from > 0)
8567 {
8568
8569
8570 it->cmp_it.to = it->cmp_it.from;
8571 }
8572 else
8573 {
8574
8575
8576 ptrdiff_t stop = it->end_charpos;
8577
8578 if (it->bidi_it.scan_dir < 0)
8579
8580
8581 stop = -1;
8582 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
8583 IT_BYTEPOS (*it), stop, Qnil, true);
8584 }
8585 }
8586 else
8587 {
8588 eassert (it->len != 0);
8589
8590 if (!it->bidi_p)
8591 {
8592 IT_BYTEPOS (*it) += it->len;
8593 IT_CHARPOS (*it) += 1;
8594 }
8595 else
8596 {
8597 int prev_scan_dir = it->bidi_it.scan_dir;
8598
8599
8600 if (it->bidi_it.new_paragraph)
8601 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it,
8602 false);
8603 bidi_move_to_visually_next (&it->bidi_it);
8604 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8605 IT_CHARPOS (*it) = it->bidi_it.charpos;
8606 if (prev_scan_dir != it->bidi_it.scan_dir)
8607 {
8608
8609
8610 ptrdiff_t stop = it->end_charpos;
8611 if (it->bidi_it.scan_dir < 0)
8612 stop = -1;
8613 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
8614 IT_BYTEPOS (*it), stop, Qnil,
8615 true);
8616 }
8617 }
8618 eassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
8619 }
8620 break;
8621
8622 case GET_FROM_C_STRING:
8623
8624 if (!it->bidi_p
8625
8626
8627
8628
8629 || IT_CHARPOS (*it) >= it->bidi_it.string.schars)
8630 {
8631 IT_BYTEPOS (*it) += it->len;
8632 IT_CHARPOS (*it) += 1;
8633 }
8634 else
8635 {
8636 bidi_move_to_visually_next (&it->bidi_it);
8637 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8638 IT_CHARPOS (*it) = it->bidi_it.charpos;
8639 }
8640 break;
8641
8642 case GET_FROM_DISPLAY_VECTOR:
8643
8644
8645
8646
8647 ++it->current.dpvec_index;
8648
8649
8650
8651 it->face_id = it->saved_face_id;
8652
8653 if (it->dpvec + it->current.dpvec_index >= it->dpend)
8654 {
8655 bool recheck_faces = it->ellipsis_p;
8656
8657 if (it->s)
8658 it->method = GET_FROM_C_STRING;
8659 else if (STRINGP (it->string))
8660 it->method = GET_FROM_STRING;
8661 else
8662 {
8663 it->method = GET_FROM_BUFFER;
8664 it->object = it->w->contents;
8665 }
8666
8667 it->dpvec = NULL;
8668 it->current.dpvec_index = -1;
8669
8670
8671 if (it->dpvec_char_len < 0)
8672 reseat_at_next_visible_line_start (it, true);
8673 else if (it->dpvec_char_len > 0)
8674 {
8675 it->len = it->dpvec_char_len;
8676 set_iterator_to_next (it, reseat_p);
8677 }
8678
8679
8680 if (recheck_faces)
8681 {
8682 if (it->method == GET_FROM_STRING)
8683 it->stop_charpos = IT_STRING_CHARPOS (*it);
8684 else
8685 it->stop_charpos = IT_CHARPOS (*it);
8686 }
8687 }
8688 break;
8689
8690 case GET_FROM_STRING:
8691
8692 eassert (it->s == NULL && STRINGP (it->string));
8693
8694
8695
8696
8697
8698 if (it->current.overlay_string_index >= 0)
8699 {
8700
8701
8702
8703 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
8704 goto consider_string_end;
8705 }
8706 else
8707 {
8708
8709
8710 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
8711 goto consider_string_end;
8712 }
8713 if (it->cmp_it.id >= 0)
8714 {
8715
8716
8717
8718 if (! it->bidi_p)
8719 {
8720 IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
8721 IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
8722 }
8723 else
8724 {
8725 int i;
8726
8727 for (i = 0; i < it->cmp_it.nchars; i++)
8728 bidi_move_to_visually_next (&it->bidi_it);
8729 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8730 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8731 }
8732
8733
8734
8735 if ((! it->bidi_p || ! it->cmp_it.reversed_p)
8736 && (it->cmp_it.to < it->cmp_it.nglyphs))
8737 {
8738
8739
8740 it->cmp_it.from = it->cmp_it.to;
8741 }
8742 else if ((it->bidi_p && it->cmp_it.reversed_p)
8743 && it->cmp_it.from > 0)
8744 {
8745
8746
8747 it->cmp_it.to = it->cmp_it.from;
8748 }
8749 else
8750 {
8751
8752
8753
8754
8755
8756
8757 ptrdiff_t stop = SCHARS (it->string);
8758
8759 if (it->bidi_p && it->bidi_it.scan_dir < 0)
8760 stop = -1;
8761 else if (it->end_charpos < stop)
8762 {
8763
8764
8765
8766 stop = it->end_charpos;
8767 }
8768 composition_compute_stop_pos (&it->cmp_it,
8769 IT_STRING_CHARPOS (*it),
8770 IT_STRING_BYTEPOS (*it), stop,
8771 it->string, true);
8772 }
8773 }
8774 else
8775 {
8776 if (!it->bidi_p
8777
8778
8779
8780
8781
8782 || IT_STRING_CHARPOS (*it) >= it->bidi_it.string.schars)
8783 {
8784 IT_STRING_BYTEPOS (*it) += it->len;
8785 IT_STRING_CHARPOS (*it) += 1;
8786 }
8787 else
8788 {
8789 int prev_scan_dir = it->bidi_it.scan_dir;
8790
8791 bidi_move_to_visually_next (&it->bidi_it);
8792 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8793 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8794
8795
8796 if (prev_scan_dir != it->bidi_it.scan_dir)
8797 {
8798 ptrdiff_t stop = SCHARS (it->string);
8799
8800 if (it->bidi_it.scan_dir < 0)
8801 stop = -1;
8802 else if (it->end_charpos < stop)
8803 stop = it->end_charpos;
8804
8805 composition_compute_stop_pos (&it->cmp_it,
8806 IT_STRING_CHARPOS (*it),
8807 IT_STRING_BYTEPOS (*it), stop,
8808 it->string, true);
8809 }
8810 }
8811 }
8812
8813 consider_string_end:
8814
8815 if (it->current.overlay_string_index >= 0)
8816 {
8817
8818
8819 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
8820 {
8821 it->ellipsis_p = false;
8822 next_overlay_string (it);
8823 if (it->ellipsis_p)
8824 setup_for_ellipsis (it, 0);
8825 }
8826 }
8827 else
8828 {
8829
8830
8831
8832
8833 if (IT_STRING_CHARPOS (*it) == SCHARS (it->string)
8834 && it->sp > 0)
8835 {
8836 pop_it (it);
8837 if (it->method == GET_FROM_STRING)
8838 goto consider_string_end;
8839 }
8840 }
8841 break;
8842
8843 case GET_FROM_IMAGE:
8844 case GET_FROM_STRETCH:
8845 case GET_FROM_XWIDGET:
8846
8847
8848
8849
8850 eassert (it->sp > 0);
8851 pop_it (it);
8852 if (it->method == GET_FROM_STRING)
8853 goto consider_string_end;
8854 break;
8855
8856 default:
8857
8858 emacs_abort ();
8859 }
8860
8861 eassert (it->method != GET_FROM_STRING
8862 || (STRINGP (it->string)
8863 && IT_STRING_CHARPOS (*it) >= 0));
8864 }
8865
8866
8867
8868
8869
8870
8871
8872
8873
8874
8875 static bool
8876 next_element_from_display_vector (struct it *it)
8877 {
8878 Lisp_Object gc;
8879 int prev_face_id = it->face_id;
8880 int next_face_id;
8881
8882
8883 eassert (it->dpvec && it->current.dpvec_index >= 0);
8884
8885 it->face_id = it->saved_face_id;
8886
8887
8888
8889 if (it->dpend - it->dpvec > 0
8890 && (gc = it->dpvec[it->current.dpvec_index], GLYPH_CODE_P (gc)))
8891 {
8892 struct face *this_face, *prev_face, *next_face;
8893
8894 it->c = GLYPH_CODE_CHAR (gc);
8895 it->len = CHAR_BYTES (it->c);
8896
8897
8898
8899
8900 if (it->dpvec_face_id >= 0)
8901 it->face_id = it->dpvec_face_id;
8902 else
8903 {
8904 int lface_id = GLYPH_CODE_FACE (gc);
8905 if (lface_id > 0)
8906 it->face_id = merge_faces (it->w, Qt, lface_id,
8907 it->saved_face_id);
8908 }
8909
8910
8911
8912
8913 this_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
8914 prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
8915
8916
8917 it->start_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
8918 && (!prev_face
8919 || prev_face->box == FACE_NO_BOX));
8920
8921
8922
8923
8924 next_face_id = it->saved_face_id;
8925 if (it->current.dpvec_index < it->dpend - it->dpvec - 1)
8926 {
8927 if (it->dpvec_face_id >= 0)
8928 next_face_id = it->dpvec_face_id;
8929 else
8930 {
8931 Lisp_Object gc = it->dpvec[it->current.dpvec_index + 1];
8932 int lface_id = GLYPH_CODE_P (gc) ? GLYPH_CODE_FACE (gc) : 0;
8933
8934 if (lface_id > 0)
8935 next_face_id = merge_faces (it->w, Qt, lface_id,
8936 it->saved_face_id);
8937 }
8938 }
8939 next_face = FACE_FROM_ID_OR_NULL (it->f, next_face_id);
8940 if (this_face && this_face->box != FACE_NO_BOX
8941 && (!next_face || next_face->box == FACE_NO_BOX))
8942 it->end_of_box_run_p = true;
8943 it->face_box_p = this_face && this_face->box != FACE_NO_BOX;
8944 }
8945 else
8946
8947 it->c = ' ', it->len = 1;
8948
8949
8950
8951
8952 it->what = IT_CHARACTER;
8953 return true;
8954 }
8955
8956
8957
8958 static void
8959 get_visually_first_element (struct it *it)
8960 {
8961 bool string_p = STRINGP (it->string) || it->s;
8962 ptrdiff_t eob = (string_p ? it->bidi_it.string.schars : ZV);
8963 ptrdiff_t bob;
8964 ptrdiff_t obegv = BEGV;
8965
8966 SET_WITH_NARROWED_BEGV (it, bob,
8967 string_p ? 0 :
8968 IT_CHARPOS (*it) < BEGV ? obegv : BEGV,
8969 it->medium_narrowing_begv);
8970
8971 if (STRINGP (it->string))
8972 {
8973 it->bidi_it.charpos = IT_STRING_CHARPOS (*it);
8974 it->bidi_it.bytepos = IT_STRING_BYTEPOS (*it);
8975 }
8976 else
8977 {
8978 it->bidi_it.charpos = IT_CHARPOS (*it);
8979 it->bidi_it.bytepos = IT_BYTEPOS (*it);
8980 }
8981
8982 if (it->bidi_it.charpos == eob)
8983 {
8984
8985
8986
8987 it->bidi_it.first_elt = false;
8988 }
8989 else if (it->bidi_it.charpos == bob
8990 || (!string_p
8991 && (FETCH_BYTE (it->bidi_it.bytepos - 1) == '\n'
8992 || FETCH_BYTE (it->bidi_it.bytepos) == '\n')))
8993 {
8994
8995
8996 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
8997 bidi_move_to_visually_next (&it->bidi_it);
8998 }
8999 else
9000 {
9001 ptrdiff_t orig_bytepos = it->bidi_it.bytepos;
9002
9003
9004
9005
9006 if (string_p)
9007 it->bidi_it.charpos = it->bidi_it.bytepos = 0;
9008 else
9009 SET_WITH_NARROWED_BEGV (it, it->bidi_it.charpos,
9010 find_newline_no_quit (IT_CHARPOS (*it),
9011 IT_BYTEPOS (*it), -1,
9012 &it->bidi_it.bytepos),
9013 it->medium_narrowing_begv);
9014 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
9015 do
9016 {
9017
9018
9019 bidi_move_to_visually_next (&it->bidi_it);
9020 }
9021 while (it->bidi_it.bytepos != orig_bytepos
9022 && it->bidi_it.charpos < eob);
9023 }
9024
9025
9026 if (STRINGP (it->string))
9027 {
9028 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
9029 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
9030 }
9031 else
9032 {
9033 IT_CHARPOS (*it) = it->bidi_it.charpos;
9034 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
9035 }
9036
9037 if (STRINGP (it->string) || !it->s)
9038 {
9039 ptrdiff_t stop, charpos, bytepos;
9040
9041 if (STRINGP (it->string))
9042 {
9043 eassert (!it->s);
9044 stop = SCHARS (it->string);
9045 if (stop > it->end_charpos)
9046 stop = it->end_charpos;
9047 charpos = IT_STRING_CHARPOS (*it);
9048 bytepos = IT_STRING_BYTEPOS (*it);
9049 }
9050 else
9051 {
9052 stop = it->end_charpos;
9053 charpos = IT_CHARPOS (*it);
9054 bytepos = IT_BYTEPOS (*it);
9055 }
9056 if (it->bidi_it.scan_dir < 0)
9057 stop = -1;
9058 composition_compute_stop_pos (&it->cmp_it, charpos, bytepos, stop,
9059 it->string, true);
9060 }
9061 }
9062
9063
9064
9065
9066
9067
9068 static bool
9069 next_element_from_string (struct it *it)
9070 {
9071 struct text_pos position;
9072
9073 eassert (STRINGP (it->string));
9074 eassert (!it->bidi_p || EQ (it->string, it->bidi_it.string.lstring));
9075 eassert (IT_STRING_CHARPOS (*it) >= 0);
9076 position = it->current.string_pos;
9077
9078
9079
9080
9081
9082 if (it->bidi_p && it->bidi_it.first_elt)
9083 {
9084 get_visually_first_element (it);
9085 SET_TEXT_POS (position, IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it));
9086 }
9087
9088
9089 if (IT_STRING_CHARPOS (*it) < it->end_charpos)
9090 {
9091 if (IT_STRING_CHARPOS (*it) >= it->stop_charpos)
9092 {
9093 if (!(!it->bidi_p
9094 || BIDI_AT_BASE_LEVEL (it->bidi_it)
9095 || IT_STRING_CHARPOS (*it) == it->stop_charpos))
9096 {
9097
9098
9099
9100
9101
9102
9103 handle_stop_backwards (it, it->stop_charpos);
9104 return GET_NEXT_DISPLAY_ELEMENT (it);
9105 }
9106 else
9107 {
9108 if (it->bidi_p)
9109 {
9110
9111
9112 it->prev_stop = it->stop_charpos;
9113
9114
9115
9116 if (BIDI_AT_BASE_LEVEL (it->bidi_it))
9117 it->base_level_stop = it->stop_charpos;
9118 }
9119 handle_stop (it);
9120
9121
9122
9123 return GET_NEXT_DISPLAY_ELEMENT (it);
9124 }
9125 }
9126 else if (it->bidi_p
9127
9128
9129
9130 && IT_STRING_CHARPOS (*it) < it->prev_stop
9131
9132
9133
9134
9135 && !BIDI_AT_BASE_LEVEL (it->bidi_it))
9136 {
9137
9138
9139
9140
9141 if (it->base_level_stop <= 0
9142 || IT_STRING_CHARPOS (*it) < it->base_level_stop)
9143 it->base_level_stop = 0;
9144 handle_stop_backwards (it, it->base_level_stop);
9145 return GET_NEXT_DISPLAY_ELEMENT (it);
9146 }
9147 }
9148
9149 if (it->current.overlay_string_index >= 0)
9150 {
9151
9152
9153
9154 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
9155 {
9156 it->what = IT_EOB;
9157 return false;
9158 }
9159 else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
9160 IT_STRING_BYTEPOS (*it),
9161 it->bidi_it.scan_dir < 0
9162 ? -1
9163 : SCHARS (it->string))
9164 && next_element_from_composition (it))
9165 {
9166 return true;
9167 }
9168 else if (STRING_MULTIBYTE (it->string))
9169 {
9170 const unsigned char *s = (SDATA (it->string)
9171 + IT_STRING_BYTEPOS (*it));
9172 it->c = check_char_and_length (s, &it->len);
9173 }
9174 else
9175 {
9176 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
9177 it->len = 1;
9178 }
9179 }
9180 else
9181 {
9182
9183
9184
9185
9186 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
9187 {
9188 it->what = IT_EOB;
9189 return false;
9190 }
9191 else if (IT_STRING_CHARPOS (*it) >= it->string_nchars)
9192 {
9193
9194 it->c = ' ', it->len = 1;
9195 CHARPOS (position) = BYTEPOS (position) = -1;
9196 }
9197 else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
9198 IT_STRING_BYTEPOS (*it),
9199 it->bidi_it.scan_dir < 0
9200 ? -1
9201 : it->string_nchars)
9202 && next_element_from_composition (it))
9203 {
9204 return true;
9205 }
9206 else if (STRING_MULTIBYTE (it->string))
9207 {
9208 const unsigned char *s = (SDATA (it->string)
9209 + IT_STRING_BYTEPOS (*it));
9210 it->c = check_char_and_length (s, &it->len);
9211 }
9212 else
9213 {
9214 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
9215 it->len = 1;
9216 }
9217 }
9218
9219
9220 it->what = IT_CHARACTER;
9221 it->object = it->string;
9222 it->position = position;
9223 return true;
9224 }
9225
9226
9227
9228
9229
9230
9231
9232
9233
9234 static bool
9235 next_element_from_c_string (struct it *it)
9236 {
9237 bool success_p = true;
9238
9239 eassert (it->s);
9240 eassert (!it->bidi_p || it->s == it->bidi_it.string.s);
9241 it->what = IT_CHARACTER;
9242 BYTEPOS (it->position) = CHARPOS (it->position) = 0;
9243 it->object = make_fixnum (0);
9244
9245
9246
9247
9248
9249 if (it->bidi_p && it->bidi_it.first_elt)
9250 get_visually_first_element (it);
9251
9252
9253
9254
9255 if (IT_CHARPOS (*it) >= it->end_charpos)
9256 {
9257
9258 it->what = IT_EOB;
9259 success_p = false;
9260 }
9261 else if (IT_CHARPOS (*it) >= it->string_nchars)
9262 {
9263
9264 it->c = ' ', it->len = 1;
9265 BYTEPOS (it->position) = CHARPOS (it->position) = -1;
9266 }
9267 else if (it->multibyte_p)
9268 it->c = check_char_and_length (it->s + IT_BYTEPOS (*it), &it->len);
9269 else
9270 it->c = it->s[IT_BYTEPOS (*it)], it->len = 1;
9271
9272 return success_p;
9273 }
9274
9275
9276
9277
9278
9279
9280
9281 static bool
9282 next_element_from_ellipsis (struct it *it)
9283 {
9284 if (it->selective_display_ellipsis_p)
9285 setup_for_ellipsis (it, it->len);
9286 else
9287 {
9288
9289
9290
9291
9292 it->saved_face_id = it->face_id;
9293 it->method = GET_FROM_BUFFER;
9294 it->object = it->w->contents;
9295 reseat_at_next_visible_line_start (it, true);
9296 it->face_before_selective_p = true;
9297 }
9298
9299 return GET_NEXT_DISPLAY_ELEMENT (it);
9300 }
9301
9302
9303
9304
9305
9306
9307
9308 static bool
9309 next_element_from_image (struct it *it)
9310 {
9311 it->what = IT_IMAGE;
9312 return true;
9313 }
9314
9315 static bool
9316 next_element_from_xwidget (struct it *it)
9317 {
9318 it->what = IT_XWIDGET;
9319 return true;
9320 }
9321
9322
9323
9324
9325
9326
9327 static bool
9328 next_element_from_stretch (struct it *it)
9329 {
9330 it->what = IT_STRETCH;
9331 return true;
9332 }
9333
9334
9335
9336
9337
9338
9339 static void
9340 compute_stop_pos_backwards (struct it *it)
9341 {
9342 const int SCAN_BACK_LIMIT = 1000;
9343 struct text_pos pos;
9344 struct display_pos save_current = it->current;
9345 struct text_pos save_position = it->position;
9346 ptrdiff_t charpos = IT_CHARPOS (*it);
9347 ptrdiff_t where_we_are = charpos;
9348 ptrdiff_t save_stop_pos = it->stop_charpos;
9349 ptrdiff_t save_end_pos = it->end_charpos;
9350
9351 eassert (NILP (it->string) && !it->s);
9352 eassert (it->bidi_p);
9353 it->bidi_p = false;
9354 do
9355 {
9356 it->end_charpos = min (charpos + 1, ZV);
9357 charpos = max (charpos - SCAN_BACK_LIMIT, BEGV);
9358 SET_TEXT_POS (pos, charpos, CHAR_TO_BYTE (charpos));
9359 reseat_1 (it, pos, false);
9360 compute_stop_pos (it);
9361
9362 if (it->stop_charpos <= charpos)
9363 emacs_abort ();
9364 }
9365 while (charpos > BEGV && it->stop_charpos >= it->end_charpos);
9366
9367 if (it->stop_charpos <= where_we_are)
9368 it->prev_stop = it->stop_charpos;
9369 else
9370 it->prev_stop = BEGV;
9371 it->bidi_p = true;
9372 it->current = save_current;
9373 it->position = save_position;
9374 it->stop_charpos = save_stop_pos;
9375 it->end_charpos = save_end_pos;
9376 }
9377
9378
9379
9380
9381
9382
9383
9384
9385
9386 static void
9387 handle_stop_backwards (struct it *it, ptrdiff_t charpos)
9388 {
9389 bool bufp = !STRINGP (it->string);
9390 ptrdiff_t where_we_are = (bufp ? IT_CHARPOS (*it) : IT_STRING_CHARPOS (*it));
9391 struct display_pos save_current = it->current;
9392 struct text_pos save_position = it->position;
9393 struct composition_it save_cmp_it = it->cmp_it;
9394 struct text_pos pos1;
9395 ptrdiff_t next_stop;
9396
9397
9398 eassert (it->bidi_p);
9399 it->bidi_p = false;
9400 do
9401 {
9402 it->prev_stop = charpos;
9403 if (bufp)
9404 {
9405 SET_TEXT_POS (pos1, charpos, CHAR_TO_BYTE (charpos));
9406 reseat_1 (it, pos1, false);
9407 }
9408 else
9409 it->current.string_pos = string_pos (charpos, it->string);
9410 compute_stop_pos (it);
9411
9412 if (it->stop_charpos <= it->prev_stop)
9413 emacs_abort ();
9414 charpos = it->stop_charpos;
9415 }
9416 while (charpos <= where_we_are);
9417
9418 it->bidi_p = true;
9419 it->current = save_current;
9420 it->position = save_position;
9421 it->cmp_it = save_cmp_it;
9422 next_stop = it->stop_charpos;
9423 it->stop_charpos = it->prev_stop;
9424 handle_stop (it);
9425 it->stop_charpos = next_stop;
9426 }
9427
9428
9429
9430
9431
9432
9433 static bool
9434 next_element_from_buffer (struct it *it)
9435 {
9436 bool success_p = true;
9437
9438 eassert (IT_CHARPOS (*it) >= BEGV);
9439 eassert (NILP (it->string) && !it->s);
9440 eassert (!it->bidi_p
9441 || (NILP (it->bidi_it.string.lstring)
9442 && it->bidi_it.string.s == NULL));
9443
9444
9445
9446
9447
9448 if (it->bidi_p && it->bidi_it.first_elt)
9449 {
9450 get_visually_first_element (it);
9451 SET_TEXT_POS (it->position, IT_CHARPOS (*it), IT_BYTEPOS (*it));
9452 }
9453
9454 if (IT_CHARPOS (*it) >= it->stop_charpos)
9455 {
9456 if (IT_CHARPOS (*it) >= it->end_charpos)
9457 {
9458 bool overlay_strings_follow_p;
9459
9460
9461
9462 if (it->overlay_strings_at_end_processed_p)
9463 overlay_strings_follow_p = false;
9464 else
9465 {
9466 it->overlay_strings_at_end_processed_p = true;
9467 overlay_strings_follow_p = get_overlay_strings (it, 0);
9468 }
9469
9470 if (overlay_strings_follow_p)
9471 success_p = GET_NEXT_DISPLAY_ELEMENT (it);
9472 else
9473 {
9474 it->what = IT_EOB;
9475 it->position = it->current.pos;
9476 success_p = false;
9477 }
9478 }
9479 else if (!(!it->bidi_p
9480 || BIDI_AT_BASE_LEVEL (it->bidi_it)
9481 || IT_CHARPOS (*it) == it->stop_charpos))
9482 {
9483
9484
9485
9486
9487
9488
9489 handle_stop_backwards (it, it->stop_charpos);
9490 it->ignore_overlay_strings_at_pos_p = false;
9491 return GET_NEXT_DISPLAY_ELEMENT (it);
9492 }
9493 else
9494 {
9495 if (it->bidi_p)
9496 {
9497
9498
9499 it->prev_stop = it->stop_charpos;
9500
9501
9502
9503 if (BIDI_AT_BASE_LEVEL (it->bidi_it))
9504 it->base_level_stop = it->stop_charpos;
9505 }
9506 handle_stop (it);
9507 it->ignore_overlay_strings_at_pos_p = false;
9508 return GET_NEXT_DISPLAY_ELEMENT (it);
9509 }
9510 }
9511 else if (it->bidi_p
9512
9513
9514
9515 && IT_CHARPOS (*it) < it->prev_stop
9516
9517
9518
9519
9520 && !BIDI_AT_BASE_LEVEL (it->bidi_it))
9521 {
9522 if (it->base_level_stop <= 0
9523 || IT_CHARPOS (*it) < it->base_level_stop)
9524 {
9525
9526
9527
9528
9529 it->base_level_stop = BEGV;
9530 compute_stop_pos_backwards (it);
9531 handle_stop_backwards (it, it->prev_stop);
9532 }
9533 else
9534 handle_stop_backwards (it, it->base_level_stop);
9535 it->ignore_overlay_strings_at_pos_p = false;
9536 return GET_NEXT_DISPLAY_ELEMENT (it);
9537 }
9538 else
9539 {
9540
9541
9542 unsigned char *p;
9543 ptrdiff_t stop;
9544
9545
9546
9547 it->ignore_overlay_strings_at_pos_p = false;
9548
9549 if (composition_break_at_point
9550 && !NILP (BVAR (current_buffer, enable_multibyte_characters))
9551 && !NILP (Vauto_composition_mode))
9552 {
9553
9554 if (it->bidi_it.scan_dir < 0)
9555 stop = (PT <= IT_CHARPOS (*it)) ? PT : -1;
9556 else
9557 stop = (IT_CHARPOS (*it) < PT
9558 && PT < it->end_charpos) ? PT : it->end_charpos;
9559 }
9560 else
9561 stop = it->bidi_it.scan_dir < 0 ? -1 : it->end_charpos;
9562 if (CHAR_COMPOSED_P (it, IT_CHARPOS (*it), IT_BYTEPOS (*it),
9563 stop)
9564 && next_element_from_composition (it))
9565 {
9566 return true;
9567 }
9568
9569
9570 p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
9571 if (it->multibyte_p && !ASCII_CHAR_P (*p))
9572 it->c = string_char_and_length (p, &it->len);
9573 else
9574 it->c = *p, it->len = 1;
9575
9576
9577 it->what = IT_CHARACTER;
9578 it->object = it->w->contents;
9579 it->position = it->current.pos;
9580
9581
9582
9583 if (it->selective)
9584 {
9585 if (it->c == '\n')
9586 {
9587
9588
9589 if (it->selective > 0
9590 && IT_CHARPOS (*it) + 1 < ZV
9591 && indented_beyond_p (IT_CHARPOS (*it) + 1,
9592 IT_BYTEPOS (*it) + 1,
9593 it->selective))
9594 {
9595 success_p = next_element_from_ellipsis (it);
9596 it->dpvec_char_len = -1;
9597 }
9598 }
9599 else if (it->c == '\r' && it->selective == -1)
9600 {
9601
9602
9603
9604 success_p = next_element_from_ellipsis (it);
9605 it->dpvec_char_len = -1;
9606 }
9607 }
9608 }
9609
9610
9611 eassert (!success_p || it->what != IT_CHARACTER || it->len > 0);
9612 return success_p;
9613 }
9614
9615
9616
9617
9618
9619
9620
9621 static bool
9622 next_element_from_composition (struct it *it)
9623 {
9624 it->what = IT_COMPOSITION;
9625 it->len = it->cmp_it.nbytes;
9626 if (STRINGP (it->string))
9627 {
9628 if (it->c < 0)
9629 {
9630 IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
9631 IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
9632 return false;
9633 }
9634 it->position = it->current.string_pos;
9635 it->object = it->string;
9636 it->c = composition_update_it (&it->cmp_it, IT_STRING_CHARPOS (*it),
9637 IT_STRING_BYTEPOS (*it), it->string);
9638 }
9639 else
9640 {
9641 if (it->c < 0)
9642 {
9643 IT_CHARPOS (*it) += it->cmp_it.nchars;
9644 IT_BYTEPOS (*it) += it->cmp_it.nbytes;
9645 if (it->bidi_p)
9646 {
9647 if (it->bidi_it.new_paragraph)
9648 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it,
9649 false);
9650
9651
9652 while (it->bidi_it.charpos < IT_CHARPOS (*it))
9653 bidi_move_to_visually_next (&it->bidi_it);
9654 }
9655 return false;
9656 }
9657 it->position = it->current.pos;
9658 it->object = it->w->contents;
9659 it->c = composition_update_it (&it->cmp_it, IT_CHARPOS (*it),
9660 IT_BYTEPOS (*it), Qnil);
9661 }
9662 return true;
9663 }
9664
9665
9666
9667
9668
9669
9670
9671
9672
9673
9674 #define IT_POS_VALID_AFTER_MOVE_P(it) \
9675 ((it)->method != GET_FROM_STRING || IT_STRING_CHARPOS (*it) == 0)
9676
9677
9678
9679
9680
9681
9682
9683
9684
9685
9686
9687
9688
9689
9690
9691
9692
9693
9694
9695
9696
9697
9698
9699
9700
9701
9702
9703
9704
9705
9706
9707
9708
9709
9710
9711 static enum move_it_result
9712 move_it_in_display_line_to (struct it *it,
9713 ptrdiff_t to_charpos, int to_x,
9714 enum move_operation_enum op)
9715 {
9716 enum move_it_result result = MOVE_UNDEFINED;
9717 struct glyph_row *saved_glyph_row;
9718 struct it wrap_it, atpos_it, atx_it, ppos_it;
9719 void *wrap_data = NULL, *atpos_data = NULL, *atx_data = NULL;
9720 void *ppos_data = NULL;
9721 bool may_wrap = false;
9722 enum it_method prev_method = it->method;
9723 ptrdiff_t closest_pos UNINIT;
9724 ptrdiff_t prev_pos = IT_CHARPOS (*it);
9725 bool saw_smaller_pos = prev_pos < to_charpos;
9726 bool line_number_pending = false;
9727
9728
9729 saved_glyph_row = it->glyph_row;
9730 it->glyph_row = NULL;
9731
9732
9733
9734
9735
9736
9737 wrap_it.sp = -1;
9738 atpos_it.sp = -1;
9739 atx_it.sp = -1;
9740
9741
9742
9743
9744
9745
9746
9747
9748 if (it->bidi_p)
9749 {
9750 if ((op & MOVE_TO_POS) && IT_CHARPOS (*it) >= to_charpos)
9751 {
9752 SAVE_IT (ppos_it, *it, ppos_data);
9753 closest_pos = IT_CHARPOS (*it);
9754 }
9755 else
9756 closest_pos = ZV;
9757 }
9758
9759 #define BUFFER_POS_REACHED_P() \
9760 ((op & MOVE_TO_POS) != 0 \
9761 && BUFFERP (it->object) \
9762 && (IT_CHARPOS (*it) == to_charpos \
9763 || ((!it->bidi_p \
9764 || BIDI_AT_BASE_LEVEL (it->bidi_it)) \
9765 && IT_CHARPOS (*it) > to_charpos) \
9766 || (it->what == IT_COMPOSITION \
9767 && ((IT_CHARPOS (*it) > to_charpos \
9768 && to_charpos >= it->cmp_it.charpos) \
9769 || (IT_CHARPOS (*it) < to_charpos \
9770 && to_charpos <= it->cmp_it.charpos)))) \
9771 && (it->method == GET_FROM_BUFFER \
9772 || (it->method == GET_FROM_DISPLAY_VECTOR \
9773 && it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
9774
9775 if (it->hpos == 0)
9776 {
9777
9778
9779
9780
9781 if (!((op && MOVE_TO_X) && to_x == it->first_visible_x)
9782 && should_produce_line_number (it))
9783 {
9784 if (it->current_x == it->first_visible_x)
9785 maybe_produce_line_number (it);
9786 else
9787 line_number_pending = true;
9788 }
9789
9790 if (it->area == TEXT_AREA && !it->string_from_prefix_prop_p)
9791 handle_line_prefix (it);
9792 }
9793
9794 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
9795 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
9796
9797 while (true)
9798 {
9799 int x, i, ascent = 0, descent = 0;
9800
9801
9802 #define IT_RESET_X_ASCENT_DESCENT(IT) \
9803 ((IT)->current_x = x, (IT)->max_ascent = ascent, \
9804 (IT)->max_descent = descent)
9805
9806
9807
9808 if ((op & MOVE_TO_POS) != 0
9809 && BUFFERP (it->object)
9810 && it->method == GET_FROM_BUFFER
9811 && (((!it->bidi_p
9812
9813
9814
9815
9816 || BIDI_AT_BASE_LEVEL (it->bidi_it))
9817 && IT_CHARPOS (*it) > to_charpos)
9818 || (it->bidi_p
9819 && (prev_method == GET_FROM_IMAGE
9820 || prev_method == GET_FROM_STRETCH
9821 || prev_method == GET_FROM_STRING)
9822
9823 && ((prev_pos < to_charpos
9824 && IT_CHARPOS (*it) >= to_charpos)
9825
9826 || (prev_pos > to_charpos
9827 && IT_CHARPOS (*it) <= to_charpos)))))
9828 {
9829 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9830 {
9831 result = MOVE_POS_MATCH_OR_ZV;
9832 break;
9833 }
9834 else if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
9835
9836
9837
9838 SAVE_IT (atpos_it, *it, atpos_data);
9839 }
9840
9841
9842
9843
9844
9845 if (!get_next_display_element (it))
9846 {
9847 result = MOVE_POS_MATCH_OR_ZV;
9848 break;
9849 }
9850
9851 if (it->line_wrap == TRUNCATE)
9852 {
9853
9854
9855
9856
9857
9858
9859 if (BUFFER_POS_REACHED_P ()
9860 && (it->pixel_width > 0
9861 || IT_CHARPOS (*it) > to_charpos
9862 || it->area != TEXT_AREA))
9863 {
9864 result = MOVE_POS_MATCH_OR_ZV;
9865 break;
9866 }
9867 }
9868 else
9869 {
9870 if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
9871 {
9872 bool next_may_wrap = may_wrap;
9873
9874 if (char_can_wrap_after (it))
9875 next_may_wrap = true;
9876 else
9877 next_may_wrap = false;
9878
9879 if (may_wrap && char_can_wrap_before (it))
9880 {
9881
9882
9883
9884
9885
9886 if (atpos_it.sp >= 0)
9887 {
9888 RESTORE_IT (it, &atpos_it, atpos_data);
9889 result = MOVE_POS_MATCH_OR_ZV;
9890 goto done;
9891 }
9892 if (atx_it.sp >= 0)
9893 {
9894 RESTORE_IT (it, &atx_it, atx_data);
9895 result = MOVE_X_REACHED;
9896 goto done;
9897 }
9898
9899 SAVE_IT (wrap_it, *it, wrap_data);
9900 }
9901
9902 may_wrap = next_may_wrap;
9903 }
9904 }
9905
9906
9907
9908 ascent = it->max_ascent;
9909 descent = it->max_descent;
9910
9911
9912
9913
9914
9915 x = it->current_x;
9916
9917 PRODUCE_GLYPHS (it);
9918
9919 if (it->area != TEXT_AREA)
9920 {
9921 prev_method = it->method;
9922 if (it->method == GET_FROM_BUFFER)
9923 prev_pos = IT_CHARPOS (*it);
9924 set_iterator_to_next (it, true);
9925 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
9926 SET_TEXT_POS (this_line_min_pos,
9927 IT_CHARPOS (*it), IT_BYTEPOS (*it));
9928 if (it->bidi_p
9929 && (op & MOVE_TO_POS)
9930 && IT_CHARPOS (*it) > to_charpos
9931 && IT_CHARPOS (*it) < closest_pos)
9932 closest_pos = IT_CHARPOS (*it);
9933 continue;
9934 }
9935
9936
9937
9938
9939
9940
9941
9942
9943
9944
9945
9946
9947
9948
9949
9950
9951
9952
9953
9954 if (it->nglyphs)
9955 {
9956
9957
9958 int single_glyph_width = it->pixel_width / it->nglyphs;
9959 int new_x;
9960 int x_before_this_char = x;
9961 int hpos_before_this_char = it->hpos;
9962
9963 for (i = 0; i < it->nglyphs; ++i, x = new_x)
9964 {
9965 new_x = x + single_glyph_width;
9966
9967
9968 if ((op & MOVE_TO_X) && new_x > to_x)
9969 {
9970 if (BUFFER_POS_REACHED_P ())
9971 {
9972 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9973 goto buffer_pos_reached;
9974 if (atpos_it.sp < 0)
9975 {
9976 SAVE_IT (atpos_it, *it, atpos_data);
9977 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
9978 }
9979 }
9980 else
9981 {
9982 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9983 {
9984 it->current_x = x;
9985 result = MOVE_X_REACHED;
9986 break;
9987 }
9988 if (atx_it.sp < 0)
9989 {
9990 SAVE_IT (atx_it, *it, atx_data);
9991 IT_RESET_X_ASCENT_DESCENT (&atx_it);
9992 }
9993 }
9994 }
9995
9996 if (
9997 it->line_wrap != TRUNCATE
9998 && (
9999 new_x > it->last_visible_x
10000
10001
10002 || (new_x == it->last_visible_x
10003 && FRAME_WINDOW_P (it->f)
10004 && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
10005 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10006 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
10007 {
10008 bool moved_forward = false;
10009
10010 if (
10011
10012 it->hpos == 0
10013 || (new_x == it->last_visible_x
10014 && FRAME_WINDOW_P (it->f)))
10015 {
10016 ++it->hpos;
10017 it->current_x = new_x;
10018
10019
10020
10021 if (i == it->nglyphs - 1)
10022 {
10023
10024
10025
10026 if (BUFFER_POS_REACHED_P ())
10027 {
10028 bool can_wrap = true;
10029
10030
10031
10032
10033
10034 if (it->line_wrap == WORD_WRAP
10035 && wrap_it.sp >= 0
10036 && may_wrap
10037 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10038 {
10039 struct it tem_it;
10040 void *tem_data = NULL;
10041
10042 SAVE_IT (tem_it, *it, tem_data);
10043 set_iterator_to_next (it, true);
10044 if (get_next_display_element (it)
10045 && !char_can_wrap_before (it))
10046 can_wrap = false;
10047 RESTORE_IT (it, &tem_it, tem_data);
10048 }
10049 if (it->line_wrap != WORD_WRAP
10050 || wrap_it.sp < 0
10051
10052
10053
10054
10055
10056
10057
10058 || (may_wrap && can_wrap
10059 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
10060 {
10061 it->hpos = hpos_before_this_char;
10062 it->current_x = x_before_this_char;
10063 result = MOVE_POS_MATCH_OR_ZV;
10064 break;
10065 }
10066 if (it->line_wrap == WORD_WRAP
10067 && atpos_it.sp < 0)
10068 {
10069 SAVE_IT (atpos_it, *it, atpos_data);
10070 atpos_it.current_x = x_before_this_char;
10071 atpos_it.hpos = hpos_before_this_char;
10072 }
10073 }
10074
10075 prev_method = it->method;
10076 if (it->method == GET_FROM_BUFFER)
10077 prev_pos = IT_CHARPOS (*it);
10078 set_iterator_to_next (it, true);
10079 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
10080 SET_TEXT_POS (this_line_min_pos,
10081 IT_CHARPOS (*it), IT_BYTEPOS (*it));
10082
10083
10084
10085
10086
10087
10088
10089 if (!FRAME_WINDOW_P (it->f)
10090 || ((it->bidi_p
10091 && it->bidi_it.paragraph_dir == R2L)
10092 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10093 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
10094 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10095 {
10096 if (!get_next_display_element (it))
10097 {
10098 result = MOVE_POS_MATCH_OR_ZV;
10099 break;
10100 }
10101 moved_forward = true;
10102 if (BUFFER_POS_REACHED_P ())
10103 {
10104 if (ITERATOR_AT_END_OF_LINE_P (it))
10105 result = MOVE_POS_MATCH_OR_ZV;
10106 else
10107 result = MOVE_LINE_CONTINUED;
10108 break;
10109 }
10110 if (ITERATOR_AT_END_OF_LINE_P (it)
10111 && (it->line_wrap != WORD_WRAP
10112 || wrap_it.sp < 0
10113 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
10114 {
10115 result = MOVE_NEWLINE_OR_CR;
10116 break;
10117 }
10118 }
10119 }
10120 }
10121 else
10122 IT_RESET_X_ASCENT_DESCENT (it);
10123
10124
10125
10126
10127
10128
10129 if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
10130
10131
10132
10133
10134
10135 && (!moved_forward || char_can_wrap_before (it)))
10136 {
10137
10138
10139 if ((op & MOVE_TO_X) && new_x == it->last_visible_x
10140 && atx_it.sp >= 0)
10141 {
10142 RESTORE_IT (it, &atx_it, atx_data);
10143 atpos_it.sp = -1;
10144 atx_it.sp = -1;
10145 result = MOVE_X_REACHED;
10146 break;
10147 }
10148 }
10149 else if (wrap_it.sp >= 0)
10150 {
10151 RESTORE_IT (it, &wrap_it, wrap_data);
10152 atpos_it.sp = -1;
10153 atx_it.sp = -1;
10154 }
10155
10156 move_trace ("move_it_in: continued at %td\n",
10157 IT_CHARPOS (*it));
10158 result = MOVE_LINE_CONTINUED;
10159 break;
10160 }
10161
10162 if (BUFFER_POS_REACHED_P ())
10163 {
10164 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
10165 goto buffer_pos_reached;
10166 if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
10167 {
10168 SAVE_IT (atpos_it, *it, atpos_data);
10169 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
10170 }
10171 }
10172
10173 if (new_x > it->first_visible_x)
10174 {
10175
10176
10177 if (line_number_pending)
10178 {
10179 line_number_pending = false;
10180 it->current_x = it->first_visible_x;
10181 maybe_produce_line_number (it);
10182 it->current_x += new_x - it->first_visible_x;
10183 }
10184
10185
10186 ++it->hpos;
10187 }
10188 }
10189
10190 if (result != MOVE_UNDEFINED)
10191 break;
10192 }
10193 else if (BUFFER_POS_REACHED_P ())
10194 {
10195 buffer_pos_reached:
10196 IT_RESET_X_ASCENT_DESCENT (it);
10197 result = MOVE_POS_MATCH_OR_ZV;
10198 break;
10199 }
10200 else if ((op & MOVE_TO_X) && it->current_x >= to_x)
10201 {
10202
10203
10204
10205
10206 eassert (it->nglyphs == 0);
10207 result = MOVE_X_REACHED;
10208 break;
10209 }
10210
10211
10212 if (ITERATOR_AT_END_OF_LINE_P (it))
10213 {
10214
10215
10216
10217
10218 if (it->bidi_p && (op & MOVE_TO_POS) != 0)
10219 {
10220 if (!saw_smaller_pos && IT_CHARPOS (*it) > to_charpos)
10221 {
10222 if (closest_pos < ZV)
10223 {
10224 RESTORE_IT (it, &ppos_it, ppos_data);
10225
10226
10227 if (closest_pos != to_charpos)
10228 move_it_in_display_line_to (it, closest_pos, -1,
10229 MOVE_TO_POS);
10230 result = MOVE_POS_MATCH_OR_ZV;
10231 }
10232 else
10233 goto buffer_pos_reached;
10234 }
10235 else if (it->line_wrap == WORD_WRAP && atpos_it.sp >= 0
10236 && IT_CHARPOS (*it) > to_charpos)
10237 goto buffer_pos_reached;
10238 else
10239 result = MOVE_NEWLINE_OR_CR;
10240 }
10241 else
10242 result = MOVE_NEWLINE_OR_CR;
10243
10244
10245
10246
10247 if (it->line_wrap == TRUNCATE
10248 && it->current_x <= it->first_visible_x
10249 && result == MOVE_NEWLINE_OR_CR
10250 && it->char_to_display == '\n')
10251 {
10252 it->max_ascent = it->ascent;
10253 it->max_descent = it->descent;
10254 }
10255
10256
10257
10258 if (result == MOVE_NEWLINE_OR_CR)
10259 it->constrain_row_ascent_descent_p = false;
10260 break;
10261 }
10262
10263 prev_method = it->method;
10264 if (it->method == GET_FROM_BUFFER)
10265 prev_pos = IT_CHARPOS (*it);
10266
10267
10268
10269
10270
10271
10272
10273
10274
10275 bool overwide_wrap_prefix =
10276 CONSP (it->object) && EQ (XCAR (it->object), Qspace)
10277 && it->sp > 0 && it->method == GET_FROM_STRETCH
10278 && it->current_x >= it->last_visible_x
10279 && it->continuation_lines_width > 0
10280 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
10281
10282
10283 if (!overwide_wrap_prefix)
10284 set_iterator_to_next (it, true);
10285 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
10286 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
10287 if (IT_CHARPOS (*it) < to_charpos)
10288 saw_smaller_pos = true;
10289 if (it->bidi_p
10290 && (op & MOVE_TO_POS)
10291 && IT_CHARPOS (*it) >= to_charpos
10292 && IT_CHARPOS (*it) < closest_pos)
10293 closest_pos = IT_CHARPOS (*it);
10294
10295
10296
10297 if (it->line_wrap == TRUNCATE
10298 && it->current_x >= it->last_visible_x)
10299 {
10300 if (!FRAME_WINDOW_P (it->f)
10301 || ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
10302 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10303 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
10304 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10305 {
10306 bool at_eob_p = false;
10307
10308 if ((at_eob_p = !get_next_display_element (it))
10309 || BUFFER_POS_REACHED_P ()
10310
10311
10312
10313
10314 || (it->bidi_p && (op & MOVE_TO_POS) != 0
10315 && !saw_smaller_pos
10316 && IT_CHARPOS (*it) > to_charpos))
10317 {
10318 if (it->bidi_p
10319 && !BUFFER_POS_REACHED_P ()
10320 && !at_eob_p && closest_pos < ZV)
10321 {
10322 RESTORE_IT (it, &ppos_it, ppos_data);
10323 if (closest_pos != to_charpos)
10324 move_it_in_display_line_to (it, closest_pos, -1,
10325 MOVE_TO_POS);
10326 }
10327 result = MOVE_POS_MATCH_OR_ZV;
10328 break;
10329 }
10330 if (ITERATOR_AT_END_OF_LINE_P (it))
10331 {
10332 result = MOVE_NEWLINE_OR_CR;
10333 break;
10334 }
10335 }
10336 else if (it->bidi_p && (op & MOVE_TO_POS) != 0
10337 && !saw_smaller_pos
10338 && IT_CHARPOS (*it) > to_charpos)
10339 {
10340 if (closest_pos < ZV)
10341 {
10342 RESTORE_IT (it, &ppos_it, ppos_data);
10343 if (closest_pos != to_charpos)
10344 move_it_in_display_line_to (it, closest_pos, -1,
10345 MOVE_TO_POS);
10346 }
10347 result = MOVE_POS_MATCH_OR_ZV;
10348 break;
10349 }
10350 result = MOVE_LINE_TRUNCATED;
10351 break;
10352 }
10353 #undef IT_RESET_X_ASCENT_DESCENT
10354 }
10355
10356 #undef BUFFER_POS_REACHED_P
10357
10358
10359
10360
10361
10362
10363 if (result == MOVE_LINE_CONTINUED
10364 && it->line_wrap == WORD_WRAP
10365 && wrap_it.sp >= 0
10366 && ((atpos_it.sp >= 0 && wrap_it.current_x < atpos_it.current_x)
10367 || (atx_it.sp >= 0 && wrap_it.current_x < atx_it.current_x)))
10368 RESTORE_IT (it, &wrap_it, wrap_data);
10369 else if (atpos_it.sp >= 0)
10370 RESTORE_IT (it, &atpos_it, atpos_data);
10371 else if (atx_it.sp >= 0)
10372 RESTORE_IT (it, &atx_it, atx_data);
10373
10374 done:
10375
10376 if (atpos_data)
10377 bidi_unshelve_cache (atpos_data, true);
10378 if (atx_data)
10379 bidi_unshelve_cache (atx_data, true);
10380 if (wrap_data)
10381 bidi_unshelve_cache (wrap_data, true);
10382 if (ppos_data)
10383 bidi_unshelve_cache (ppos_data, true);
10384
10385
10386
10387 it->glyph_row = saved_glyph_row;
10388 return result;
10389 }
10390
10391
10392 void
10393 move_it_in_display_line (struct it *it,
10394 ptrdiff_t to_charpos, int to_x,
10395 enum move_operation_enum op)
10396 {
10397 if (it->line_wrap == WORD_WRAP
10398 && (op & MOVE_TO_X))
10399 {
10400 struct it save_it;
10401 void *save_data = NULL;
10402 int skip;
10403
10404 SAVE_IT (save_it, *it, save_data);
10405 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
10406
10407
10408
10409
10410 if (skip == MOVE_LINE_CONTINUED)
10411 {
10412 int prev_x = max (it->current_x - 1, 0);
10413 RESTORE_IT (it, &save_it, save_data);
10414 move_it_in_display_line_to
10415 (it, -1, prev_x, MOVE_TO_X);
10416 }
10417 else
10418 bidi_unshelve_cache (save_data, true);
10419 }
10420 else
10421 move_it_in_display_line_to (it, to_charpos, to_x, op);
10422 }
10423
10424
10425
10426
10427
10428
10429
10430
10431
10432
10433
10434
10435
10436
10437
10438
10439 int
10440 move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos, int op)
10441 {
10442 enum move_it_result skip, skip2 = MOVE_X_REACHED;
10443 int line_height, line_start_x = 0, reached = 0;
10444 int max_current_x = 0;
10445 void *backup_data = NULL;
10446 ptrdiff_t orig_charpos = -1;
10447 enum it_method orig_method = NUM_IT_METHODS;
10448
10449 for (;;)
10450 {
10451 orig_charpos = IT_CHARPOS (*it);
10452 orig_method = it->method;
10453 if (op & MOVE_TO_VPOS)
10454 {
10455
10456
10457 if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0)
10458 {
10459 if (it->vpos == to_vpos)
10460 {
10461 reached = 1;
10462 break;
10463 }
10464 else
10465 skip = move_it_in_display_line_to (it, -1, -1, 0);
10466 }
10467 else
10468 {
10469
10470
10471 if (it->vpos == to_vpos)
10472 {
10473 reached = 2;
10474 break;
10475 }
10476
10477 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
10478
10479 if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos)
10480 {
10481 reached = 3;
10482 break;
10483 }
10484 else if (skip == MOVE_X_REACHED && it->vpos != to_vpos)
10485 {
10486
10487 skip = move_it_in_display_line_to (it, to_charpos,
10488 -1, MOVE_TO_POS);
10489 if (skip == MOVE_POS_MATCH_OR_ZV)
10490 {
10491 reached = 4;
10492 break;
10493 }
10494 }
10495 }
10496 }
10497 else if (op & MOVE_TO_Y)
10498 {
10499 struct it it_backup;
10500
10501 if (it->line_wrap == WORD_WRAP)
10502 SAVE_IT (it_backup, *it, backup_data);
10503
10504
10505
10506
10507
10508
10509
10510
10511
10512
10513
10514
10515
10516 skip = move_it_in_display_line_to
10517 (it, to_charpos, ((op & MOVE_TO_X) ? to_x : 0),
10518 (MOVE_TO_X | (op & MOVE_TO_POS)));
10519
10520
10521 if (skip == MOVE_POS_MATCH_OR_ZV)
10522 reached = 5;
10523 else if (skip == MOVE_X_REACHED)
10524 {
10525
10526
10527
10528
10529 line_height = it->max_ascent + it->max_descent;
10530 if (to_y >= it->current_y
10531 && to_y < it->current_y + line_height)
10532 {
10533 reached = 6;
10534 break;
10535 }
10536 SAVE_IT (it_backup, *it, backup_data);
10537 move_trace ("move_it: from %td\n", IT_CHARPOS (*it));
10538 skip2 = move_it_in_display_line_to (it, to_charpos, -1,
10539 op & MOVE_TO_POS);
10540 move_trace ("move_it: to %td\n", IT_CHARPOS (*it));
10541 line_height = it->max_ascent + it->max_descent;
10542 move_trace ("move_it: line_height = %d\n", line_height);
10543
10544 if (to_y >= it->current_y
10545 && to_y < it->current_y + line_height)
10546 {
10547
10548
10549
10550
10551
10552
10553
10554
10555 int max_ascent = it->max_ascent;
10556 int max_descent = it->max_descent;
10557
10558 RESTORE_IT (it, &it_backup, backup_data);
10559 it->max_ascent = max_ascent;
10560 it->max_descent = max_descent;
10561 reached = 6;
10562 }
10563 else
10564 {
10565 skip = skip2;
10566 if (skip == MOVE_POS_MATCH_OR_ZV)
10567 {
10568 reached = 7;
10569
10570
10571
10572
10573
10574
10575
10576 if (to_charpos > 0
10577 && IT_CHARPOS (*it) != to_charpos
10578 && ((IT_CHARPOS (it_backup) > to_charpos)
10579 == (IT_CHARPOS (*it) > to_charpos)))
10580 {
10581 int max_ascent = it->max_ascent;
10582 int max_descent = it->max_descent;
10583
10584 RESTORE_IT (it, &it_backup, backup_data);
10585 it->max_ascent = max_ascent;
10586 it->max_descent = max_descent;
10587 }
10588 }
10589 }
10590 }
10591 else
10592 {
10593
10594 line_height = it->max_ascent + it->max_descent;
10595 move_trace ("move_it: line_height = %d\n", line_height);
10596
10597 if (to_y >= it->current_y
10598 && to_y < it->current_y + line_height)
10599 {
10600 if (to_y > it->current_y)
10601 max_current_x = max (it->current_x, max_current_x);
10602
10603
10604
10605
10606
10607 if (skip == MOVE_LINE_CONTINUED
10608 && it->line_wrap == WORD_WRAP)
10609 {
10610 int prev_x = max (it->current_x - 1, 0);
10611 RESTORE_IT (it, &it_backup, backup_data);
10612 skip = move_it_in_display_line_to
10613 (it, -1, prev_x, MOVE_TO_X);
10614 }
10615
10616 reached = 6;
10617 }
10618 }
10619
10620 if (reached)
10621 {
10622 max_current_x = max (it->current_x, max_current_x);
10623 break;
10624 }
10625 }
10626 else if (BUFFERP (it->object)
10627 && (it->method == GET_FROM_BUFFER
10628 || it->method == GET_FROM_STRETCH)
10629 && IT_CHARPOS (*it) >= to_charpos
10630
10631
10632
10633
10634
10635 && !(it->bidi_p
10636 && it->bidi_it.scan_dir == -1))
10637 skip = MOVE_POS_MATCH_OR_ZV;
10638 else
10639 skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
10640
10641 switch (skip)
10642 {
10643 case MOVE_POS_MATCH_OR_ZV:
10644 max_current_x = max (it->current_x, max_current_x);
10645 reached = 8;
10646 goto out;
10647
10648 case MOVE_NEWLINE_OR_CR:
10649 max_current_x = max (it->current_x, max_current_x);
10650 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10651 it->override_ascent = -1;
10652 set_iterator_to_next (it, true);
10653 it->continuation_lines_width = 0;
10654 break;
10655
10656 case MOVE_LINE_TRUNCATED:
10657 max_current_x = it->last_visible_x;
10658 it->continuation_lines_width = 0;
10659 reseat_at_next_visible_line_start (it, false);
10660 if ((op & MOVE_TO_POS) != 0
10661 && (IT_CHARPOS (*it) > to_charpos
10662 || (IT_CHARPOS (*it) == to_charpos
10663
10664
10665 && to_charpos == ZV
10666 && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n')
10667
10668
10669
10670 && (it->sp == 0
10671 || (STRINGP (it->string)
10672 && (it->current.overlay_string_index < 0
10673 || (it->current.overlay_string_index >= 0
10674 && it->current.overlay_string_index
10675 >= it->n_overlay_strings - 1))
10676 && IT_STRING_CHARPOS (*it) >= it->end_charpos)))))
10677 {
10678 reached = 9;
10679 goto out;
10680 }
10681 break;
10682
10683 case MOVE_LINE_CONTINUED:
10684 max_current_x = it->last_visible_x;
10685
10686
10687
10688
10689 if (it->c == '\t')
10690 {
10691 it->continuation_lines_width += it->last_visible_x;
10692
10693
10694
10695 if (it->current_x != it->last_visible_x
10696 && (op & MOVE_TO_VPOS)
10697 && !(op & (MOVE_TO_X | MOVE_TO_POS)))
10698 {
10699 line_start_x = it->current_x + it->pixel_width
10700 - it->last_visible_x;
10701 if (FRAME_WINDOW_P (it->f))
10702 {
10703 struct face *face = FACE_FROM_ID (it->f, it->face_id);
10704 struct font *face_font = face->font;
10705
10706
10707
10708
10709
10710
10711
10712 eassert (face_font);
10713 if (face_font)
10714 {
10715 if (line_start_x < face_font->space_width)
10716 line_start_x
10717 += it->tab_width * face_font->space_width;
10718 }
10719 }
10720 set_iterator_to_next (it, false);
10721 }
10722 }
10723 else
10724 {
10725
10726
10727
10728
10729
10730
10731
10732
10733 if (IT_CHARPOS (*it) == orig_charpos
10734 && it->method == orig_method
10735 && orig_method == GET_FROM_BUFFER)
10736 set_iterator_to_next (it, false);
10737 it->continuation_lines_width += it->current_x;
10738 }
10739 break;
10740
10741 default:
10742 emacs_abort ();
10743 }
10744
10745
10746 it->current_x = line_start_x;
10747 line_start_x = 0;
10748 it->hpos = 0;
10749 it->line_number_produced_p = false;
10750 it->current_y += it->max_ascent + it->max_descent;
10751 ++it->vpos;
10752 last_height = it->max_ascent + it->max_descent;
10753 it->max_ascent = it->max_descent = 0;
10754 }
10755
10756 out:
10757
10758
10759
10760
10761
10762
10763 if (!FRAME_WINDOW_P (it->f)
10764 && op & MOVE_TO_POS
10765 && IT_CHARPOS (*it) == to_charpos
10766 && it->what == IT_CHARACTER
10767 && it->nglyphs > 1
10768 && it->line_wrap == WINDOW_WRAP
10769 && it->current_x == it->last_visible_x - 1
10770 && it->c != '\n'
10771 && it->c != '\t'
10772 && it->w->window_end_valid
10773 && it->vpos < it->w->window_end_vpos)
10774 {
10775 it->continuation_lines_width += it->current_x;
10776 it->current_x = it->hpos = it->max_ascent = it->max_descent = 0;
10777 it->current_y += it->max_ascent + it->max_descent;
10778 ++it->vpos;
10779 last_height = it->max_ascent + it->max_descent;
10780 }
10781
10782 if (backup_data)
10783 bidi_unshelve_cache (backup_data, true);
10784
10785 move_trace ("move_it_to: reached %d\n", reached);
10786
10787 return max_current_x;
10788 }
10789
10790
10791
10792
10793
10794
10795
10796
10797
10798
10799
10800 void
10801 move_it_vertically_backward (struct it *it, int dy)
10802 {
10803 int nlines, h;
10804 struct it it2, it3;
10805 void *it2data = NULL, *it3data = NULL;
10806 ptrdiff_t start_pos;
10807 int nchars_per_row
10808 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
10809 ptrdiff_t pos_limit;
10810
10811 move_further_back:
10812 eassert (dy >= 0);
10813
10814 start_pos = IT_CHARPOS (*it);
10815
10816
10817 nlines = max (1, dy / default_line_pixel_height (it->w));
10818 if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
10819 pos_limit = BEGV;
10820 else
10821 pos_limit = max (start_pos - nlines * nchars_per_row, BEGV);
10822
10823
10824
10825
10826 while (nlines-- && IT_CHARPOS (*it) > pos_limit)
10827 back_to_previous_visible_line_start (it);
10828
10829
10830
10831
10832
10833 reseat_1 (it, it->current.pos, true);
10834
10835
10836 it->current_x = it->hpos = 0;
10837
10838 it->continuation_lines_width = 0;
10839
10840
10841
10842
10843
10844 SAVE_IT (it2, *it, it2data);
10845 it2.max_ascent = it2.max_descent = 0;
10846 do
10847 {
10848 move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
10849 MOVE_TO_POS | MOVE_TO_VPOS);
10850 }
10851 while (!(IT_POS_VALID_AFTER_MOVE_P (&it2)
10852
10853
10854
10855
10856
10857
10858 || (it2.method == GET_FROM_STRING
10859 && IT_CHARPOS (it2) == start_pos
10860 && SREF (it2.string, IT_STRING_BYTEPOS (it2) - 1) == '\n')));
10861 eassert (IT_CHARPOS (*it) >= BEGV);
10862 SAVE_IT (it3, it2, it3data);
10863
10864 move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
10865 eassert (IT_CHARPOS (*it) >= BEGV);
10866
10867
10868 h = it2.current_y - it->current_y;
10869
10870 nlines = it2.vpos - it->vpos;
10871
10872
10873
10874 it->vpos -= nlines;
10875 it->current_y -= h;
10876
10877 if (dy == 0)
10878 {
10879
10880
10881
10882 RESTORE_IT (it, it, it2data);
10883 if (nlines > 0)
10884 move_it_by_lines (it, nlines);
10885
10886
10887
10888
10889
10890
10891 if (it->bidi_p
10892 && !it->continuation_lines_width
10893 && !STRINGP (it->string)
10894 && IT_CHARPOS (*it) > BEGV
10895 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
10896 {
10897 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
10898
10899 dec_both (&cp, &bp);
10900 SET_WITH_NARROWED_BEGV (it, cp,
10901 find_newline_no_quit (cp, bp, -1, NULL),
10902 get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
10903 move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS);
10904 }
10905 bidi_unshelve_cache (it3data, true);
10906 }
10907 else
10908 {
10909
10910
10911 int target_y = it->current_y + h - dy;
10912 int y0 = it3.current_y;
10913 int y1;
10914 int line_height;
10915
10916 RESTORE_IT (&it3, &it3, it3data);
10917 y1 = line_bottom_y (&it3);
10918 line_height = y1 - y0;
10919 RESTORE_IT (it, it, it2data);
10920
10921
10922 if (target_y < it->current_y
10923
10924
10925
10926
10927 && (it->current_y - target_y
10928 > min (window_box_height (it->w), line_height * 2 / 3))
10929 && IT_CHARPOS (*it) > BEGV)
10930 {
10931 move_trace (" not far enough -> move_vert %d\n",
10932 target_y - it->current_y);
10933 dy = it->current_y - target_y;
10934 goto move_further_back;
10935 }
10936 else if (target_y >= it->current_y + line_height
10937 && IT_CHARPOS (*it) < ZV)
10938 {
10939
10940
10941
10942
10943
10944
10945
10946
10947 if (!FRAME_WINDOW_P (it->f))
10948 move_it_vertically (it, target_y - it->current_y);
10949 else
10950 {
10951 struct text_pos last_pos;
10952 int last_y, last_vpos;
10953 do
10954 {
10955 last_pos = it->current.pos;
10956 last_y = it->current_y;
10957 last_vpos = it->vpos;
10958 move_it_by_lines (it, 1);
10959 }
10960 while (target_y > it->current_y && IT_CHARPOS (*it) < ZV);
10961 if (it->current_y > target_y)
10962 {
10963 reseat (it, last_pos, true);
10964 it->current_y = last_y;
10965 it->vpos = last_vpos;
10966 }
10967 }
10968 }
10969 }
10970 }
10971
10972
10973
10974
10975
10976
10977 void
10978 move_it_vertically (struct it *it, int dy)
10979 {
10980 if (dy <= 0)
10981 move_it_vertically_backward (it, -dy);
10982 else
10983 {
10984 move_trace ("move_it_v: from %td, %d\n", IT_CHARPOS (*it), dy);
10985 move_it_to (it, ZV, -1, it->current_y + dy, -1,
10986 MOVE_TO_POS | MOVE_TO_Y);
10987 move_trace ("move_it_v: to %td\n", IT_CHARPOS (*it));
10988
10989
10990
10991 if (IT_CHARPOS (*it) == ZV
10992 && ZV > BEGV
10993 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
10994 move_it_by_lines (it, 0);
10995 }
10996 }
10997
10998
10999
11000
11001 void
11002 move_it_past_eol (struct it *it)
11003 {
11004 enum move_it_result rc;
11005
11006 rc = move_it_in_display_line_to (it, Z, 0, MOVE_TO_POS);
11007 if (rc == MOVE_NEWLINE_OR_CR)
11008 set_iterator_to_next (it, false);
11009 }
11010
11011
11012
11013
11014
11015
11016
11017
11018
11019
11020 void
11021 move_it_by_lines (struct it *it, ptrdiff_t dvpos)
11022 {
11023
11024
11025
11026
11027
11028
11029
11030
11031
11032
11033
11034
11035
11036
11037
11038
11039
11040 if (dvpos == 0)
11041 {
11042
11043 move_it_vertically_backward (it, 0);
11044
11045 last_height = 0;
11046 }
11047 else if (dvpos > 0)
11048 {
11049 move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
11050 if (!IT_POS_VALID_AFTER_MOVE_P (it))
11051 {
11052
11053
11054
11055
11056
11057
11058
11059
11060
11061
11062 move_it_to (it, IT_CHARPOS (*it) + it->string_from_display_prop_p,
11063 -1, -1, -1, MOVE_TO_POS);
11064 }
11065 }
11066 else
11067 {
11068 struct it it2;
11069 void *it2data = NULL;
11070 ptrdiff_t start_charpos, orig_charpos, i;
11071 int nchars_per_row
11072 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
11073 bool hit_pos_limit = false;
11074 ptrdiff_t pos_limit;
11075
11076
11077
11078
11079 dvpos += it->vpos;
11080 orig_charpos = IT_CHARPOS (*it);
11081 move_it_vertically_backward (it, 0);
11082 dvpos -= it->vpos;
11083
11084
11085
11086 start_charpos = IT_CHARPOS (*it);
11087 if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
11088 pos_limit = BEGV;
11089 else
11090 pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV);
11091
11092 for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i)
11093 back_to_previous_visible_line_start (it);
11094 if (i > 0 && IT_CHARPOS (*it) <= pos_limit)
11095 hit_pos_limit = true;
11096 reseat (it, it->current.pos, true);
11097
11098
11099 while (!IT_POS_VALID_AFTER_MOVE_P (it))
11100 {
11101
11102 dvpos += it->vpos;
11103 move_it_vertically_backward (it, 0);
11104 dvpos -= it->vpos;
11105 if (IT_POS_VALID_AFTER_MOVE_P (it))
11106 break;
11107
11108
11109 back_to_previous_visible_line_start (it);
11110 reseat (it, it->current.pos, true);
11111 dvpos--;
11112 }
11113
11114 it->current_x = it->hpos = 0;
11115
11116
11117
11118 SAVE_IT (it2, *it, it2data);
11119 it2.vpos = it2.current_y = 0;
11120 move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
11121 it->vpos -= it2.vpos;
11122 it->current_y -= it2.current_y;
11123 it->current_x = it->hpos = 0;
11124
11125
11126 if (it2.vpos > -dvpos)
11127 {
11128 int delta = it2.vpos + dvpos;
11129
11130 RESTORE_IT (&it2, &it2, it2data);
11131 SAVE_IT (it2, *it, it2data);
11132 move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
11133
11134
11135 if (it->vpos - it2.vpos > delta || IT_CHARPOS (*it) == orig_charpos)
11136 RESTORE_IT (it, &it2, it2data);
11137 else
11138 bidi_unshelve_cache (it2data, true);
11139 }
11140 else if (hit_pos_limit && pos_limit > BEGV
11141 && dvpos < 0 && it2.vpos < -dvpos)
11142 {
11143
11144
11145
11146
11147
11148
11149
11150
11151 dvpos += it2.vpos;
11152 RESTORE_IT (it, it, it2data);
11153 for (i = -dvpos; i > 0; --i)
11154 {
11155 back_to_previous_visible_line_start (it);
11156 it->vpos--;
11157 }
11158 reseat_1 (it, it->current.pos, true);
11159 }
11160 else
11161 RESTORE_IT (it, it, it2data);
11162 }
11163 }
11164
11165 int
11166 partial_line_height (struct it *it_origin)
11167 {
11168
11169
11170
11171
11172
11173 if (XBUFFER (it_origin->w->contents)->long_line_optimizations_p
11174 && it_origin->line_wrap == TRUNCATE)
11175 return 0;
11176
11177 int partial_height;
11178 void *it_data = NULL;
11179 struct it it;
11180 SAVE_IT (it, *it_origin, it_data);
11181 move_it_to (&it, ZV, -1, it.last_visible_y, -1,
11182 MOVE_TO_POS | MOVE_TO_Y);
11183 if (it.what == IT_EOB)
11184 {
11185 int vis_height = it.last_visible_y - it.current_y;
11186 int height = it.ascent + it.descent;
11187 partial_height = (vis_height < height) ? vis_height : 0;
11188 }
11189 else
11190 {
11191 int last_line_y = it.current_y;
11192 move_it_by_lines (&it, 1);
11193 partial_height = (it.current_y > it.last_visible_y)
11194 ? it.last_visible_y - last_line_y : 0;
11195 }
11196 RESTORE_IT (&it, &it, it_data);
11197 return partial_height;
11198 }
11199
11200
11201
11202
11203
11204
11205
11206
11207
11208
11209
11210
11211 static enum move_it_result
11212 fast_move_it_horizontally (struct it *it, ptrdiff_t nchars)
11213 {
11214 ptrdiff_t nl_bytepos;
11215 ptrdiff_t nl_pos = find_newline_no_quit (IT_CHARPOS (*it), IT_BYTEPOS (*it),
11216 1, &nl_bytepos);
11217 struct text_pos new_pos;
11218 enum move_it_result move_result;
11219
11220 if (nl_pos - IT_CHARPOS (*it) > nchars)
11221 {
11222 SET_TEXT_POS (new_pos,
11223 IT_CHARPOS (*it) + nchars,
11224 CHAR_TO_BYTE (IT_CHARPOS (*it) + nchars));
11225 move_result = MOVE_X_REACHED;
11226 }
11227 else
11228 {
11229 if (nl_bytepos < ZV_BYTE
11230 || (nl_bytepos > BEGV_BYTE
11231 && FETCH_BYTE (nl_bytepos - 1) == '\n'))
11232 {
11233 nl_pos--;
11234 nl_bytepos--;
11235 move_result = MOVE_NEWLINE_OR_CR;
11236 }
11237 else
11238 move_result = MOVE_POS_MATCH_OR_ZV;
11239 SET_TEXT_POS (new_pos, nl_pos, nl_bytepos);
11240 }
11241 reseat (it, new_pos, false);
11242 return move_result;
11243 }
11244
11245
11246
11247 bool
11248 in_display_vector_p (struct it *it)
11249 {
11250 return (it->method == GET_FROM_DISPLAY_VECTOR
11251 && it->current.dpvec_index > 0
11252 && it->dpvec + it->current.dpvec_index != it->dpend);
11253 }
11254
11255
11256
11257
11258
11259 static Lisp_Object
11260 window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
11261 Lisp_Object x_limit, Lisp_Object y_limit,
11262 Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
11263 {
11264 struct window *w = decode_live_window (window);
11265 struct it it;
11266 ptrdiff_t start, end, bpos;
11267 struct text_pos startp;
11268 void *itdata = NULL;
11269 int c, max_x = 0, max_y = 0, x = 0, y = 0, vertical_offset = 0, doff = 0;
11270
11271 if (NILP (from))
11272 {
11273 start = BEGV;
11274 bpos = BEGV_BYTE;
11275 }
11276 else if (EQ (from, Qt))
11277 {
11278 start = BEGV;
11279 bpos = BEGV_BYTE;
11280 while (bpos < ZV_BYTE)
11281 {
11282 c = FETCH_BYTE (bpos);
11283 if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))
11284 break;
11285 inc_both (&start, &bpos);
11286 }
11287 while (bpos > BEGV_BYTE)
11288 {
11289 dec_both (&start, &bpos);
11290 c = FETCH_BYTE (bpos);
11291 if (!(c == ' ' || c == '\t'))
11292 break;
11293 }
11294 }
11295 else if (CONSP (from))
11296 {
11297 start = clip_to_bounds (BEGV, fix_position (XCAR (from)), ZV);
11298 bpos = CHAR_TO_BYTE (start);
11299 CHECK_FIXNUM (XCDR (from));
11300 vertical_offset = XFIXNUM (XCDR (from));
11301 }
11302 else
11303 {
11304 start = clip_to_bounds (BEGV, fix_position (from), ZV);
11305 bpos = CHAR_TO_BYTE (start);
11306 }
11307
11308 SET_TEXT_POS (startp, start, bpos);
11309
11310 if (NILP (to))
11311 end = ZV;
11312 else if (EQ (to, Qt))
11313 {
11314 end = ZV;
11315 bpos = ZV_BYTE;
11316 while (bpos > BEGV_BYTE)
11317 {
11318 dec_both (&end, &bpos);
11319 c = FETCH_BYTE (bpos);
11320 if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))
11321 {
11322 inc_both (&end, &bpos);
11323 break;
11324 }
11325 }
11326 while (bpos < ZV_BYTE)
11327 {
11328 c = fetch_char_advance (&end, &bpos);
11329 if (!(c == ' ' || c == '\t'))
11330 break;
11331 }
11332 }
11333 else
11334 end = clip_to_bounds (start, fix_position (to), ZV);
11335
11336 if (RANGED_FIXNUMP (0, x_limit, INT_MAX))
11337 max_x = XFIXNUM (x_limit);
11338 else if (!NILP (x_limit))
11339 max_x = INT_MAX;
11340
11341 if (NILP (y_limit))
11342 max_y = INT_MAX;
11343 else if (RANGED_FIXNUMP (0, y_limit, INT_MAX))
11344 max_y = XFIXNUM (y_limit);
11345
11346 itdata = bidi_shelve_cache ();
11347
11348 start_display (&it, w, startp);
11349
11350 int start_y = it.current_y;
11351
11352
11353
11354
11355
11356
11357
11358 it.bidi_p = false;
11359
11360 int start_x;
11361 if (vertical_offset != 0)
11362 {
11363 int last_y;
11364 it.current_y = 0;
11365
11366 move_it_by_lines (&it, 0);
11367
11368
11369
11370
11371
11372 if (vertical_offset < 0)
11373 {
11374 while (it.current_y > vertical_offset)
11375 {
11376 last_y = it.current_y;
11377 move_it_vertically_backward (&it,
11378 (abs (vertical_offset)
11379 + it.current_y));
11380
11381 if (it.current_y == last_y)
11382 break;
11383 }
11384 }
11385 else
11386 {
11387 move_it_vertically (&it, vertical_offset);
11388 }
11389
11390 it.current_y = (WINDOW_TAB_LINE_HEIGHT (w)
11391 + WINDOW_HEADER_LINE_HEIGHT (w));
11392 start = clip_to_bounds (BEGV, IT_CHARPOS (it), ZV);
11393 start_y = it.current_y;
11394 start_x = it.current_x;
11395 }
11396 else
11397 {
11398
11399
11400
11401 reseat_at_previous_visible_line_start (&it);
11402 it.current_x = it.hpos = 0;
11403 if (IT_CHARPOS (it) != start)
11404 {
11405 void *it1data = NULL;
11406 struct it it1;
11407
11408 SAVE_IT (it1, it, it1data);
11409 move_it_to (&it, start, -1, -1, -1, MOVE_TO_POS);
11410
11411
11412
11413
11414
11415 if (IT_CHARPOS (it) > start && start > BEGV)
11416 {
11417 ptrdiff_t it1pos = IT_CHARPOS (it1);
11418 int it1_x = it1.current_x;
11419
11420 RESTORE_IT (&it, &it1, it1data);
11421
11422
11423
11424
11425
11426 if (start - 1 > it1pos)
11427 move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
11428 else
11429 move_it_in_display_line (&it, start, it1_x + 1,
11430 MOVE_TO_POS | MOVE_TO_X);
11431 move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
11432 start_x = it.current_x;
11433
11434
11435
11436 if (IT_CHARPOS (it) == start - 1)
11437 start_x += it.pixel_width;
11438 }
11439 else
11440 {
11441 start_x = it.current_x;
11442 bidi_unshelve_cache (it1data, true);
11443 }
11444 }
11445 else
11446 start_x = it.current_x;
11447 }
11448
11449
11450 int move_op = MOVE_TO_POS | MOVE_TO_Y;
11451 int to_x = -1;
11452 it.current_y = start_y;
11453
11454
11455 if (FETCH_BYTE (start) == '\n')
11456 it.current_x = 0;
11457 if (!NILP (x_limit))
11458 {
11459 it.last_visible_x = max_x;
11460
11461
11462
11463 move_op |= MOVE_TO_X;
11464 to_x = INT_MAX;
11465 }
11466
11467 void *it2data = NULL;
11468 struct it it2;
11469 SAVE_IT (it2, it, it2data);
11470
11471 x = move_it_to (&it, end, to_x, max_y, -1, move_op);
11472
11473
11474
11475
11476
11477 if (IT_CHARPOS (it) > end)
11478 {
11479 end--;
11480 RESTORE_IT (&it, &it2, it2data);
11481 x = move_it_to (&it, end, to_x, max_y, -1, move_op);
11482
11483
11484
11485 if (IT_CHARPOS (it) == end)
11486 {
11487 x += it.pixel_width;
11488
11489
11490 if (!NILP (ignore_line_at_end))
11491 doff = (max (it.max_ascent, it.ascent)
11492 + max (it.max_descent, it.descent));
11493 else
11494 {
11495 it.max_ascent = max (it.max_ascent, it.ascent);
11496 it.max_descent = max (it.max_descent, it.descent);
11497 }
11498 }
11499 }
11500 else
11501 bidi_unshelve_cache (it2data, true);
11502
11503 if (!NILP (x_limit))
11504 {
11505
11506 if (x > max_x)
11507 x = max_x;
11508 }
11509
11510
11511
11512
11513 if (it.current_y > start_y)
11514 start_x = 0;
11515
11516
11517
11518 if (!NILP (ignore_line_at_end))
11519 y = (it.current_y + doff
11520 - WINDOW_TAB_LINE_HEIGHT (w)
11521 - WINDOW_HEADER_LINE_HEIGHT (w));
11522 else
11523 y = (it.current_y + it.max_ascent + it.max_descent + doff
11524 - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w));
11525
11526
11527 if (y > max_y)
11528 y = max_y;
11529
11530 if ((EQ (mode_lines, Qtab_line) || EQ (mode_lines, Qt))
11531 && window_wants_tab_line (w))
11532
11533 {
11534 Lisp_Object window_tab_line_format
11535 = window_parameter (w, Qtab_line_format);
11536
11537 y = y + display_mode_line (w, TAB_LINE_FACE_ID,
11538 NILP (window_tab_line_format)
11539 ? BVAR (current_buffer, tab_line_format)
11540 : window_tab_line_format);
11541 }
11542
11543 if ((EQ (mode_lines, Qheader_line) || EQ (mode_lines, Qt))
11544 && window_wants_header_line (w))
11545 {
11546 Lisp_Object window_header_line_format
11547 = window_parameter (w, Qheader_line_format);
11548
11549 y = y + display_mode_line (w, HEADER_LINE_FACE_ID,
11550 NILP (window_header_line_format)
11551 ? BVAR (current_buffer, header_line_format)
11552 : window_header_line_format);
11553 }
11554
11555 if ((EQ (mode_lines, Qmode_line) || EQ (mode_lines, Qt))
11556 && window_wants_mode_line (w))
11557 {
11558 Lisp_Object window_mode_line_format
11559 = window_parameter (w, Qmode_line_format);
11560
11561 y = y + display_mode_line (w, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w),
11562 NILP (window_mode_line_format)
11563 ? BVAR (current_buffer, mode_line_format)
11564 : window_mode_line_format);
11565 }
11566
11567 bidi_unshelve_cache (itdata, false);
11568
11569 return (!vertical_offset
11570 ? Fcons (make_fixnum (x - start_x), make_fixnum (y))
11571 : list3i (x - start_x, y, start));
11572 }
11573
11574 DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 7, 0,
11575 doc:
11576
11577
11578
11579
11580
11581
11582
11583
11584
11585
11586
11587
11588
11589
11590
11591
11592
11593
11594
11595
11596
11597
11598
11599
11600
11601
11602
11603
11604
11605
11606
11607
11608
11609
11610
11611
11612
11613
11614
11615
11616
11617
11618
11619
11620
11621
11622
11623
11624
11625
11626
11627
11628
11629
11630 )
11631 (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit,
11632 Lisp_Object y_limit, Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
11633 {
11634 struct window *w = decode_live_window (window);
11635 struct buffer *b = XBUFFER (w->contents);
11636 struct buffer *old_b = NULL;
11637 Lisp_Object value;
11638
11639 if (b != current_buffer)
11640 {
11641 old_b = current_buffer;
11642 set_buffer_internal_1 (b);
11643 }
11644
11645 value = window_text_pixel_size (window, from, to, x_limit, y_limit, mode_lines,
11646 ignore_line_at_end);
11647
11648 if (old_b)
11649 set_buffer_internal_1 (old_b);
11650
11651 return value;
11652 }
11653
11654 DEFUN ("buffer-text-pixel-size", Fbuffer_text_pixel_size, Sbuffer_text_pixel_size, 0, 4, 0,
11655 doc:
11656
11657
11658
11659
11660
11661
11662
11663
11664
11665
11666
11667
11668 )
11669 (Lisp_Object buffer_or_name, Lisp_Object window, Lisp_Object x_limit,
11670 Lisp_Object y_limit)
11671 {
11672 struct window *w = decode_live_window (window);
11673 struct buffer *b = (NILP (buffer_or_name)
11674 ? current_buffer
11675 : XBUFFER (Fget_buffer (buffer_or_name)));
11676 Lisp_Object buffer, value;
11677 specpdl_ref count = SPECPDL_INDEX ();
11678
11679 XSETBUFFER (buffer, b);
11680
11681
11682
11683
11684 record_unwind_protect (unwind_with_echo_area_buffer,
11685 with_echo_area_buffer_unwind_data (w));
11686
11687 set_buffer_internal_1 (b);
11688
11689 ptrdiff_t base_line_pos = w->base_line_pos;
11690 int end_valid = w->window_end_valid;
11691 if (!EQ (buffer, w->contents))
11692 {
11693 wset_buffer (w, buffer);
11694 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
11695 set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
11696 }
11697
11698 value = window_text_pixel_size (window, Qnil, Qnil, x_limit, y_limit, Qnil,
11699 Qnil);
11700
11701 unbind_to (count, Qnil);
11702
11703
11704
11705 w->base_line_pos = base_line_pos;
11706 w->window_end_valid = end_valid;
11707
11708 return value;
11709 }
11710
11711
11712 DEFUN ("display--line-is-continued-p", Fdisplay__line_is_continued_p,
11713 Sdisplay__line_is_continued_p, 0, 0, 0,
11714 doc: )
11715 (void)
11716 {
11717 struct buffer *oldb = current_buffer;
11718 struct window *w = XWINDOW (selected_window);
11719 enum move_it_result rc = MOVE_POS_MATCH_OR_ZV;
11720
11721 set_buffer_internal_1 (XBUFFER (w->contents));
11722
11723 if (PT < ZV)
11724 {
11725 struct text_pos startpos;
11726 struct it it;
11727 void *itdata;
11728
11729
11730 Lisp_Object opoint = Fpoint_marker ();
11731
11732
11733
11734 Fvertical_motion (make_fixnum (0), selected_window, Qnil);
11735 SET_TEXT_POS (startpos, PT, PT_BYTE);
11736 itdata = bidi_shelve_cache ();
11737 start_display (&it, w, startpos);
11738
11739 if (it.line_wrap != TRUNCATE)
11740 {
11741 it.glyph_row = NULL;
11742 rc = move_it_in_display_line_to (&it, ZV, -1, MOVE_TO_POS);
11743 }
11744 SET_PT_BOTH (marker_position (opoint), marker_byte_position (opoint));
11745 bidi_unshelve_cache (itdata, false);
11746 }
11747 set_buffer_internal_1 (oldb);
11748
11749 return rc == MOVE_LINE_CONTINUED ? Qt : Qnil;
11750 }
11751
11752
11753
11754
11755
11756
11757
11758
11759 static ptrdiff_t
11760 format_nargs (char const *format)
11761 {
11762 ptrdiff_t nargs = 0;
11763 for (char const *p = format; (p = strchr (p, '%')); p++)
11764 if (p[1] == '%')
11765 p++;
11766 else
11767 nargs++;
11768 return nargs;
11769 }
11770
11771
11772
11773
11774 void
11775 add_to_log (const char *format, ...)
11776 {
11777 va_list ap;
11778 va_start (ap, format);
11779 vadd_to_log (format, ap);
11780 va_end (ap);
11781 }
11782
11783 void
11784 vadd_to_log (char const *format, va_list ap)
11785 {
11786 ptrdiff_t form_nargs = format_nargs (format);
11787 ptrdiff_t nargs = 1 + form_nargs;
11788 Lisp_Object args[10];
11789 eassert (nargs <= ARRAYELTS (args));
11790 AUTO_STRING (args0, format);
11791 args[0] = args0;
11792 for (ptrdiff_t i = 1; i <= nargs; i++)
11793 args[i] = va_arg (ap, Lisp_Object);
11794 Lisp_Object msg = Qnil;
11795 msg = Fformat_message (nargs, args);
11796
11797 ptrdiff_t len = SBYTES (msg) + 1;
11798 USE_SAFE_ALLOCA;
11799 char *buffer = SAFE_ALLOCA (len);
11800 memcpy (buffer, SDATA (msg), len);
11801
11802 message_dolog (buffer, len - 1, true, STRING_MULTIBYTE (msg));
11803 SAFE_FREE ();
11804 }
11805
11806
11807
11808
11809 void
11810 message_log_maybe_newline (void)
11811 {
11812 if (message_log_need_newline)
11813 message_dolog ("", 0, true, false);
11814 }
11815
11816
11817
11818
11819
11820
11821
11822
11823
11824
11825
11826 void
11827 message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
11828 {
11829 const unsigned char *msg = (const unsigned char *) m;
11830
11831 if (!NILP (Vmemory_full))
11832 return;
11833
11834 if (!NILP (Vmessage_log_max))
11835 {
11836 struct buffer *oldbuf;
11837 Lisp_Object oldpoint, oldbegv, oldzv;
11838 int old_windows_or_buffers_changed = windows_or_buffers_changed;
11839 ptrdiff_t point_at_end = 0;
11840 ptrdiff_t zv_at_end = 0;
11841 Lisp_Object old_deactivate_mark;
11842
11843 old_deactivate_mark = Vdeactivate_mark;
11844 oldbuf = current_buffer;
11845
11846
11847
11848 if (! STRINGP (Vmessages_buffer_name))
11849 Vmessages_buffer_name = build_string ("*Messages*");
11850
11851
11852 bool newbuffer = NILP (Fget_buffer (Vmessages_buffer_name));
11853 Fset_buffer (Fget_buffer_create (Vmessages_buffer_name, Qnil));
11854 if (newbuffer
11855 && !NILP (Ffboundp (intern ("messages-buffer-mode"))))
11856 call0 (intern ("messages-buffer-mode"));
11857
11858 bset_undo_list (current_buffer, Qt);
11859 bset_cache_long_scans (current_buffer, Qnil);
11860
11861 oldpoint = message_dolog_marker1;
11862 set_marker_restricted_both (oldpoint, Qnil, PT, PT_BYTE);
11863 oldbegv = message_dolog_marker2;
11864 set_marker_restricted_both (oldbegv, Qnil, BEGV, BEGV_BYTE);
11865 oldzv = message_dolog_marker3;
11866 set_marker_restricted_both (oldzv, Qnil, ZV, ZV_BYTE);
11867
11868 if (PT == Z)
11869 point_at_end = 1;
11870 if (ZV == Z)
11871 zv_at_end = 1;
11872
11873 BEGV = BEG;
11874 BEGV_BYTE = BEG_BYTE;
11875 ZV = Z;
11876 ZV_BYTE = Z_BYTE;
11877 TEMP_SET_PT_BOTH (Z, Z_BYTE);
11878
11879
11880
11881 if (multibyte
11882 && NILP (BVAR (current_buffer, enable_multibyte_characters)))
11883 {
11884
11885
11886 for (ptrdiff_t i = 0; i < nbytes; )
11887 {
11888 int char_bytes, c = check_char_and_length (msg + i, &char_bytes);
11889 char work = CHAR_TO_BYTE8 (c);
11890 insert_1_both (&work, 1, 1, true, false, false);
11891 i += char_bytes;
11892 }
11893 }
11894 else if (! multibyte
11895 && ! NILP (BVAR (current_buffer, enable_multibyte_characters)))
11896 {
11897
11898
11899 for (ptrdiff_t i = 0; i < nbytes; i++)
11900 {
11901 int c = make_char_multibyte (msg[i]);
11902 unsigned char str[MAX_MULTIBYTE_LENGTH];
11903 int char_bytes = CHAR_STRING (c, str);
11904 insert_1_both ((char *) str, 1, char_bytes, true, false, false);
11905 }
11906 }
11907 else if (nbytes)
11908 insert_1_both (m, chars_in_text (msg, nbytes), nbytes,
11909 true, false, false);
11910
11911 if (nlflag)
11912 {
11913 ptrdiff_t this_bol, this_bol_byte, prev_bol, prev_bol_byte;
11914 intmax_t dups;
11915
11916
11917
11918
11919
11920 specpdl_ref count = SPECPDL_INDEX ();
11921 specbind (Qinhibit_modification_hooks, Qt);
11922
11923 insert_1_both ("\n", 1, 1, true, false, false);
11924
11925 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, false);
11926 this_bol = PT;
11927 this_bol_byte = PT_BYTE;
11928
11929
11930
11931 if (this_bol > BEG)
11932 {
11933 scan_newline (PT, PT_BYTE, BEG, BEG_BYTE, -2, false);
11934 prev_bol = PT;
11935 prev_bol_byte = PT_BYTE;
11936
11937 dups = message_log_check_duplicate (prev_bol_byte,
11938 this_bol_byte);
11939 if (dups)
11940 {
11941 del_range_both (prev_bol, prev_bol_byte,
11942 this_bol, this_bol_byte, false);
11943 if (dups > 1)
11944 {
11945 char dupstr[sizeof " [ times]"
11946 + INT_STRLEN_BOUND (dups)];
11947
11948
11949
11950 int duplen = sprintf (dupstr, " [%"PRIdMAX" times]",
11951 dups);
11952 TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
11953 insert_1_both (dupstr, duplen, duplen,
11954 true, false, true);
11955 }
11956 }
11957 }
11958
11959
11960
11961
11962
11963 if (FIXNATP (Vmessage_log_max))
11964 {
11965 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE,
11966 -XFIXNAT (Vmessage_log_max) - 1, false);
11967 del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, false);
11968 }
11969
11970 unbind_to (count, Qnil);
11971 }
11972 BEGV = marker_position (oldbegv);
11973 BEGV_BYTE = marker_byte_position (oldbegv);
11974
11975 if (zv_at_end)
11976 {
11977 ZV = Z;
11978 ZV_BYTE = Z_BYTE;
11979 }
11980 else
11981 {
11982 ZV = marker_position (oldzv);
11983 ZV_BYTE = marker_byte_position (oldzv);
11984 }
11985
11986 if (point_at_end)
11987 TEMP_SET_PT_BOTH (Z, Z_BYTE);
11988 else
11989
11990
11991 TEMP_SET_PT_BOTH (marker_position (oldpoint),
11992 marker_byte_position (oldpoint));
11993
11994 unchain_marker (XMARKER (oldpoint));
11995 unchain_marker (XMARKER (oldbegv));
11996 unchain_marker (XMARKER (oldzv));
11997
11998
11999
12000
12001
12002
12003
12004 windows_or_buffers_changed = old_windows_or_buffers_changed;
12005 bset_redisplay (current_buffer);
12006
12007 set_buffer_internal (oldbuf);
12008
12009 message_log_need_newline = !nlflag;
12010 Vdeactivate_mark = old_deactivate_mark;
12011 }
12012 }
12013
12014
12015
12016
12017
12018
12019
12020
12021 static intmax_t
12022 message_log_check_duplicate (ptrdiff_t prev_bol_byte, ptrdiff_t this_bol_byte)
12023 {
12024 ptrdiff_t i;
12025 ptrdiff_t len = Z_BYTE - 1 - this_bol_byte;
12026 bool seen_dots = false;
12027 unsigned char *p1 = BUF_BYTE_ADDRESS (current_buffer, prev_bol_byte);
12028 unsigned char *p2 = BUF_BYTE_ADDRESS (current_buffer, this_bol_byte);
12029
12030 for (i = 0; i < len; i++)
12031 {
12032 if (i >= 3 && p1[i - 3] == '.' && p1[i - 2] == '.' && p1[i - 1] == '.')
12033 seen_dots = true;
12034 if (p1[i] != p2[i])
12035 return seen_dots;
12036 }
12037 p1 += len;
12038 if (*p1 == '\n')
12039 return 2;
12040 if (*p1++ == ' ' && *p1++ == '[')
12041 {
12042 char *pend;
12043 intmax_t n = strtoimax ((char *) p1, &pend, 10);
12044 if (0 < n && n < INTMAX_MAX && strncmp (pend, " times]\n", 8) == 0)
12045 return n + 1;
12046 }
12047 return 0;
12048 }
12049
12050
12051
12052
12053
12054
12055
12056
12057
12058 void
12059 message3 (Lisp_Object m)
12060 {
12061 clear_message (true, true);
12062 cancel_echoing ();
12063
12064
12065 message_log_maybe_newline ();
12066 if (STRINGP (m))
12067 {
12068 ptrdiff_t nbytes = SBYTES (m);
12069 bool multibyte = STRING_MULTIBYTE (m);
12070 char *buffer;
12071 USE_SAFE_ALLOCA;
12072 SAFE_ALLOCA_STRING (buffer, m);
12073 message_dolog (buffer, nbytes, true, multibyte);
12074 SAFE_FREE ();
12075 }
12076 if (! inhibit_message)
12077 message3_nolog (m);
12078 }
12079
12080
12081
12082 static void
12083 message_to_stderr (Lisp_Object m)
12084 {
12085 if (noninteractive_need_newline)
12086 {
12087 noninteractive_need_newline = false;
12088 errputc ('\n');
12089 }
12090 if (STRINGP (m))
12091 {
12092 Lisp_Object coding_system = Vlocale_coding_system;
12093 Lisp_Object s;
12094
12095 if (!NILP (Vcoding_system_for_write))
12096 coding_system = Vcoding_system_for_write;
12097 if (!NILP (coding_system))
12098 s = code_convert_string_norecord (m, coding_system, true);
12099 else
12100 s = m;
12101
12102 errwrite (SDATA (s), SBYTES (s));
12103 }
12104 if (STRINGP (m) || !cursor_in_echo_area)
12105 errputc ('\n');
12106 }
12107
12108
12109
12110
12111
12112
12113 void
12114 message3_nolog (Lisp_Object m)
12115 {
12116 struct frame *sf = SELECTED_FRAME ();
12117
12118 if (FRAME_INITIAL_P (sf))
12119 message_to_stderr (m);
12120
12121
12122
12123 else if (INTERACTIVE && sf->glyphs_initialized_p)
12124 {
12125
12126
12127 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
12128 Lisp_Object frame = XWINDOW (mini_window)->frame;
12129 struct frame *f = XFRAME (frame);
12130
12131 if (FRAME_VISIBLE_P (sf) && !FRAME_VISIBLE_P (f))
12132 Fmake_frame_visible (frame);
12133
12134 if (STRINGP (m) && SCHARS (m) > 0)
12135 {
12136 set_message (m);
12137 if (minibuffer_auto_raise)
12138 Fraise_frame (frame);
12139
12140
12141 echo_message_buffer = Qnil;
12142 }
12143 else
12144 clear_message (true, true);
12145
12146 do_pending_window_change (false);
12147 echo_area_display (true);
12148 do_pending_window_change (false);
12149 if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
12150 (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
12151 }
12152 }
12153
12154
12155
12156
12157
12158
12159
12160
12161
12162
12163 void
12164 message1 (const char *m)
12165 {
12166 message3 (m ? build_unibyte_string (m) : Qnil);
12167 }
12168
12169
12170
12171
12172 void
12173 message1_nolog (const char *m)
12174 {
12175 message3_nolog (m ? build_unibyte_string (m) : Qnil);
12176 }
12177
12178
12179
12180
12181 void
12182 message_with_string (const char *m, Lisp_Object string, bool log)
12183 {
12184 CHECK_STRING (string);
12185
12186 bool need_message;
12187 if (noninteractive)
12188 need_message = !!m;
12189 else if (!INTERACTIVE)
12190 need_message = false;
12191 else
12192 {
12193
12194
12195
12196 Lisp_Object mini_window;
12197 struct frame *f, *sf = SELECTED_FRAME ();
12198
12199
12200
12201 mini_window = FRAME_MINIBUF_WINDOW (sf);
12202 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
12203
12204
12205
12206
12207 need_message = f->glyphs_initialized_p;
12208 }
12209
12210 if (need_message)
12211 {
12212 AUTO_STRING (fmt, m);
12213 Lisp_Object msg = CALLN (Fformat_message, fmt, string);
12214
12215 if (noninteractive)
12216 message_to_stderr (msg);
12217 else
12218 {
12219 if (log)
12220 message3 (msg);
12221 else
12222 message3_nolog (msg);
12223
12224
12225
12226 message_buf_print = false;
12227 }
12228 }
12229 }
12230
12231
12232
12233
12234
12235
12236
12237
12238
12239
12240
12241
12242 static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
12243 vmessage (const char *m, va_list ap)
12244 {
12245 if (noninteractive)
12246 {
12247 if (m)
12248 {
12249 if (noninteractive_need_newline)
12250 putc ('\n', stderr);
12251 noninteractive_need_newline = false;
12252 vfprintf (stderr, m, ap);
12253 if (!cursor_in_echo_area)
12254 putc ('\n', stderr);
12255 fflush (stderr);
12256 }
12257 }
12258 else if (INTERACTIVE)
12259 {
12260
12261
12262
12263 Lisp_Object mini_window;
12264 struct frame *f, *sf = SELECTED_FRAME ();
12265
12266
12267
12268 mini_window = FRAME_MINIBUF_WINDOW (sf);
12269 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
12270
12271
12272
12273
12274 if (f->glyphs_initialized_p)
12275 {
12276 if (m)
12277 {
12278 ptrdiff_t len;
12279 ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f);
12280 USE_SAFE_ALLOCA;
12281 char *message_buf = SAFE_ALLOCA (maxsize + 1);
12282
12283 len = doprnt (message_buf, maxsize, m, 0, ap);
12284
12285 message3 (make_string (message_buf, len));
12286 SAFE_FREE ();
12287 }
12288 else
12289 message1 (0);
12290
12291
12292
12293 message_buf_print = false;
12294 }
12295 }
12296 }
12297
12298
12299 void
12300 message (const char *m, ...)
12301 {
12302 va_list ap;
12303 va_start (ap, m);
12304 vmessage (m, ap);
12305 va_end (ap);
12306 }
12307
12308
12309
12310
12311
12312
12313 void
12314 update_echo_area (void)
12315 {
12316 if (!NILP (echo_area_buffer[0]))
12317 {
12318 Lisp_Object string;
12319 string = Fcurrent_message ();
12320 message3 (string);
12321 }
12322 }
12323
12324
12325
12326
12327
12328 static void
12329 ensure_echo_area_buffers (void)
12330 {
12331 for (int i = 0; i < 2; i++)
12332 if (!BUFFERP (echo_buffer[i])
12333 || !BUFFER_LIVE_P (XBUFFER (echo_buffer[i])))
12334 {
12335 Lisp_Object old_buffer = echo_buffer[i];
12336 static char const name_fmt[] = " *Echo Area %d*";
12337 char name[sizeof name_fmt + INT_STRLEN_BOUND (int)];
12338 AUTO_STRING_WITH_LEN (lname, name, sprintf (name, name_fmt, i));
12339 echo_buffer[i] = Fget_buffer_create (lname, Qnil);
12340 bset_truncate_lines (XBUFFER (echo_buffer[i]), Qnil);
12341
12342
12343
12344
12345 for (int j = 0; j < 2; j++)
12346 if (EQ (old_buffer, echo_area_buffer[j]))
12347 echo_area_buffer[j] = echo_buffer[i];
12348 }
12349 }
12350
12351
12352
12353
12354
12355
12356
12357
12358
12359
12360
12361
12362
12363
12364
12365
12366
12367
12368 static bool
12369 with_echo_area_buffer (struct window *w, int which,
12370 bool (*fn) (void *, Lisp_Object),
12371 void *a1, Lisp_Object a2)
12372 {
12373 Lisp_Object buffer;
12374 bool this_one, the_other, clear_buffer_p, rc;
12375 specpdl_ref count = SPECPDL_INDEX ();
12376
12377
12378 ensure_echo_area_buffers ();
12379
12380 clear_buffer_p = false;
12381
12382 if (which == 0)
12383 this_one = false, the_other = true;
12384 else if (which > 0)
12385 this_one = true, the_other = false;
12386 else
12387 {
12388 this_one = false, the_other = true;
12389 clear_buffer_p = true;
12390
12391
12392
12393 if (!NILP (echo_area_buffer[this_one])
12394 && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
12395 echo_area_buffer[this_one] = Qnil;
12396 }
12397
12398
12399
12400 if (NILP (echo_area_buffer[this_one]))
12401 {
12402 echo_area_buffer[this_one]
12403 = (EQ (echo_area_buffer[the_other], echo_buffer[this_one])
12404 ? echo_buffer[the_other]
12405 : echo_buffer[this_one]);
12406 clear_buffer_p = true;
12407 }
12408
12409 buffer = echo_area_buffer[this_one];
12410
12411
12412
12413 if (echo_kboard == NULL && EQ (buffer, echo_message_buffer))
12414 cancel_echoing ();
12415
12416 record_unwind_protect (unwind_with_echo_area_buffer,
12417 with_echo_area_buffer_unwind_data (w));
12418
12419
12420
12421
12422
12423
12424
12425
12426 set_buffer_internal_1 (XBUFFER (buffer));
12427 if (w)
12428 {
12429 wset_buffer (w, buffer);
12430 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
12431 set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
12432 }
12433
12434 bset_undo_list (current_buffer, Qt);
12435 bset_read_only (current_buffer, Qnil);
12436 specbind (Qinhibit_read_only, Qt);
12437 specbind (Qinhibit_modification_hooks, Qt);
12438
12439 if (clear_buffer_p && Z > BEG)
12440 del_range (BEG, Z);
12441
12442 eassert (BEGV >= BEG);
12443 eassert (ZV <= Z && ZV >= BEGV);
12444
12445 rc = fn (a1, a2);
12446
12447 eassert (BEGV >= BEG);
12448 eassert (ZV <= Z && ZV >= BEGV);
12449
12450 unbind_to (count, Qnil);
12451 return rc;
12452 }
12453
12454
12455
12456
12457
12458 static Lisp_Object
12459 with_echo_area_buffer_unwind_data (struct window *w)
12460 {
12461 int i = 0;
12462 Lisp_Object vector, tmp;
12463
12464
12465
12466 vector = Vwith_echo_area_save_vector;
12467 Vwith_echo_area_save_vector = Qnil;
12468
12469 if (NILP (vector))
12470 vector = make_nil_vector (11);
12471
12472 XSETBUFFER (tmp, current_buffer); ASET (vector, i, tmp); ++i;
12473 ASET (vector, i, Vdeactivate_mark); ++i;
12474 ASET (vector, i, make_fixnum (windows_or_buffers_changed)); ++i;
12475
12476 if (w)
12477 {
12478 XSETWINDOW (tmp, w); ASET (vector, i, tmp); ++i;
12479 ASET (vector, i, w->contents); ++i;
12480 ASET (vector, i, make_fixnum (marker_position (w->pointm))); ++i;
12481 ASET (vector, i, make_fixnum (marker_byte_position (w->pointm))); ++i;
12482 ASET (vector, i, make_fixnum (marker_position (w->old_pointm))); ++i;
12483 ASET (vector, i, make_fixnum (marker_byte_position (w->old_pointm))); ++i;
12484 ASET (vector, i, make_fixnum (marker_position (w->start))); ++i;
12485 ASET (vector, i, make_fixnum (marker_byte_position (w->start))); ++i;
12486 }
12487 else
12488 {
12489 int end = i + 8;
12490 for (; i < end; ++i)
12491 ASET (vector, i, Qnil);
12492 }
12493
12494 eassert (i == ASIZE (vector));
12495 return vector;
12496 }
12497
12498
12499
12500
12501
12502 static void
12503 unwind_with_echo_area_buffer (Lisp_Object vector)
12504 {
12505 set_buffer_internal_1 (XBUFFER (AREF (vector, 0)));
12506 Vdeactivate_mark = AREF (vector, 1);
12507 windows_or_buffers_changed = XFIXNAT (AREF (vector, 2));
12508
12509 if (WINDOWP (AREF (vector, 3)))
12510 {
12511 struct window *w;
12512 Lisp_Object buffer;
12513
12514 w = XWINDOW (AREF (vector, 3));
12515 buffer = AREF (vector, 4);
12516
12517 wset_buffer (w, buffer);
12518 set_marker_restricted_both (w->pointm, buffer,
12519 XFIXNAT (AREF (vector, 5)),
12520 XFIXNAT (AREF (vector, 6)));
12521 set_marker_restricted_both (w->old_pointm, buffer,
12522 XFIXNAT (AREF (vector, 7)),
12523 XFIXNAT (AREF (vector, 8)));
12524 set_marker_restricted_both (w->start, buffer,
12525 XFIXNAT (AREF (vector, 9)),
12526 XFIXNAT (AREF (vector, 10)));
12527 }
12528
12529 Vwith_echo_area_save_vector = vector;
12530 }
12531
12532
12533
12534
12535
12536 void
12537 setup_echo_area_for_printing (bool multibyte_p)
12538 {
12539
12540 if (! FRAME_LIVE_P (XFRAME (selected_frame)))
12541 Fkill_emacs (Qnil, Qnil);
12542
12543 ensure_echo_area_buffers ();
12544
12545 if (!message_buf_print)
12546 {
12547
12548
12549 if (EQ (echo_area_buffer[1], echo_buffer[0]))
12550 echo_area_buffer[0] = echo_buffer[1];
12551 else
12552 echo_area_buffer[0] = echo_buffer[0];
12553
12554
12555 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
12556 bset_truncate_lines (current_buffer, Qnil);
12557
12558 if (Z > BEG)
12559 {
12560 specpdl_ref count = SPECPDL_INDEX ();
12561 specbind (Qinhibit_read_only, Qt);
12562
12563 del_range (BEG, Z);
12564 unbind_to (count, Qnil);
12565 }
12566 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
12567
12568
12569
12570
12571
12572
12573
12574 if (unibyte_display_via_language_environment
12575 && !multibyte_p
12576 && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
12577 Fset_buffer_multibyte (Qnil);
12578 else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
12579 Fset_buffer_multibyte (Qt);
12580
12581
12582 if (minibuffer_auto_raise)
12583 {
12584 struct frame *sf = SELECTED_FRAME ();
12585 Lisp_Object mini_window;
12586 mini_window = FRAME_MINIBUF_WINDOW (sf);
12587 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
12588 }
12589
12590 message_log_maybe_newline ();
12591 message_buf_print = true;
12592 }
12593 else
12594 {
12595 if (NILP (echo_area_buffer[0]))
12596 {
12597 if (EQ (echo_area_buffer[1], echo_buffer[0]))
12598 echo_area_buffer[0] = echo_buffer[1];
12599 else
12600 echo_area_buffer[0] = echo_buffer[0];
12601 }
12602
12603 if (current_buffer != XBUFFER (echo_area_buffer[0]))
12604 {
12605
12606 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
12607 bset_truncate_lines (current_buffer, Qnil);
12608 }
12609 }
12610 }
12611
12612
12613
12614
12615
12616
12617
12618 static bool
12619 display_echo_area (struct window *w)
12620 {
12621 bool no_message_p, window_height_changed_p;
12622
12623
12624
12625
12626
12627
12628 specpdl_ref count = inhibit_garbage_collection ();
12629
12630
12631
12632
12633
12634 bool i = display_last_displayed_message_p;
12635
12636
12637
12638 no_message_p = NILP (echo_area_buffer[i]);
12639
12640 window_height_changed_p
12641 = with_echo_area_buffer (w, display_last_displayed_message_p,
12642 display_echo_area_1, w, Qnil);
12643
12644 if (no_message_p)
12645 echo_area_buffer[i] = Qnil;
12646
12647 unbind_to (count, Qnil);
12648 return window_height_changed_p;
12649 }
12650
12651
12652
12653
12654
12655
12656
12657
12658 static bool
12659 display_echo_area_1 (void *a1, Lisp_Object a2)
12660 {
12661 struct window *w = a1;
12662 Lisp_Object window;
12663 struct text_pos start;
12664
12665
12666
12667
12668 forget_escape_and_glyphless_faces ();
12669
12670
12671
12672
12673 bool window_height_changed_p = resize_mini_window (w, false);
12674
12675
12676 SET_TEXT_POS_FROM_MARKER (start, w->start);
12677
12678
12679 clear_glyph_matrix (w->desired_matrix);
12680 XSETWINDOW (window, w);
12681 void *itdata = bidi_shelve_cache ();
12682 try_window (window, start, 0);
12683 bidi_unshelve_cache (itdata, false);
12684
12685 return window_height_changed_p;
12686 }
12687
12688
12689
12690
12691
12692
12693 void
12694 resize_echo_area_exactly (void)
12695 {
12696 if (BUFFERP (echo_area_buffer[0])
12697 && WINDOWP (echo_area_window))
12698 {
12699 struct window *w = XWINDOW (echo_area_window);
12700 Lisp_Object resize_exactly = (minibuf_level == 0 ? Qt : Qnil);
12701 bool resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
12702 w, resize_exactly);
12703 if (resized_p)
12704 {
12705 windows_or_buffers_changed = 42;
12706 update_mode_lines = 30;
12707 redisplay_internal ();
12708 }
12709 }
12710 }
12711
12712
12713
12714
12715
12716
12717
12718
12719 static bool
12720 resize_mini_window_1 (void *a1, Lisp_Object exactly)
12721 {
12722 return resize_mini_window (a1, !NILP (exactly));
12723 }
12724
12725
12726
12727
12728
12729
12730
12731
12732
12733
12734
12735
12736
12737 bool
12738 resize_mini_window (struct window *w, bool exact_p)
12739 {
12740 struct frame *f = XFRAME (w->frame);
12741 int old_height = WINDOW_BOX_TEXT_HEIGHT (w);
12742
12743 eassert (MINI_WINDOW_P (w));
12744
12745
12746
12747
12748
12749
12750
12751 if (!NILP (Vinhibit_redisplay))
12752 return false;
12753
12754
12755 if (redisplay_adhoc_scroll_in_resize_mini_windows)
12756 set_marker_both (w->start, w->contents,
12757 BUF_BEGV (XBUFFER (w->contents)),
12758 BUF_BEGV_BYTE (XBUFFER (w->contents)));
12759
12760
12761 if ((NILP (Vresize_mini_windows)
12762 && (NILP (resize_mini_frames) || !FRAME_MINIBUF_ONLY_P (f)))
12763 || (FRAME_X_P (f) && FRAME_OUTPUT_DATA (f) == NULL))
12764 return false;
12765
12766 if (FRAME_MINIBUF_ONLY_P (f))
12767 {
12768 if (!NILP (resize_mini_frames))
12769 safe_call1 (Qwindow__resize_mini_frame, WINDOW_FRAME (w));
12770 }
12771 else
12772 {
12773 struct it it;
12774 int unit = FRAME_LINE_HEIGHT (f);
12775 int height, max_height;
12776 struct text_pos start;
12777 struct buffer *old_current_buffer = NULL;
12778 int windows_height = FRAME_INNER_HEIGHT (f);
12779
12780 if (current_buffer != XBUFFER (w->contents))
12781 {
12782 old_current_buffer = current_buffer;
12783 set_buffer_internal (XBUFFER (w->contents));
12784 }
12785
12786 init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
12787
12788
12789 if (FLOATP (Vmax_mini_window_height))
12790 max_height = XFLOAT_DATA (Vmax_mini_window_height) * windows_height;
12791 else if (FIXNUMP (Vmax_mini_window_height))
12792 max_height = XFIXNUM (Vmax_mini_window_height) * unit;
12793 else
12794 max_height = windows_height / 4;
12795
12796
12797 max_height = clip_to_bounds (unit, max_height, windows_height);
12798
12799
12800 last_height = 0;
12801 move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
12802
12803
12804 if (it.max_ascent == 0 && it.max_descent == 0)
12805 {
12806 height = it.current_y;
12807
12808
12809
12810
12811
12812 if (!(it.line_wrap == TRUNCATE
12813 && it.current_x <= it.first_visible_x
12814 && ZV_BYTE > 1
12815 && FETCH_BYTE (ZV_BYTE - 1) != '\n'))
12816 height += last_height;
12817 }
12818 else
12819 height = it.current_y + it.max_ascent + it.max_descent;
12820 height -= min (it.extra_line_spacing, it.max_extra_line_spacing);
12821
12822
12823 if (height > max_height)
12824 {
12825 height = (max_height / unit) * unit;
12826 if (redisplay_adhoc_scroll_in_resize_mini_windows)
12827 {
12828 init_iterator (&it, w, ZV, ZV_BYTE, NULL, DEFAULT_FACE_ID);
12829 move_it_vertically_backward (&it, height - unit);
12830
12831
12832
12833
12834
12835
12836
12837
12838
12839 move_it_by_lines (&it, 0);
12840 start = it.current.pos;
12841
12842
12843 w->start_at_line_beg = false;
12844 SET_MARKER_FROM_TEXT_POS (w->start, start);
12845 }
12846 }
12847 else
12848 {
12849 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
12850 SET_MARKER_FROM_TEXT_POS (w->start, start);
12851 }
12852
12853 if (EQ (Vresize_mini_windows, Qgrow_only))
12854 {
12855
12856
12857 if (height > old_height)
12858 grow_mini_window (w, height - old_height);
12859 else if (height < old_height && (exact_p || BEGV == ZV))
12860 shrink_mini_window (w);
12861 }
12862 else if (height != old_height)
12863
12864 grow_mini_window (w, height - old_height);
12865
12866 if (old_current_buffer)
12867 set_buffer_internal (old_current_buffer);
12868 }
12869
12870 return WINDOW_BOX_TEXT_HEIGHT (w) != old_height;
12871 }
12872
12873
12874
12875
12876
12877 Lisp_Object
12878 current_message (void)
12879 {
12880 Lisp_Object msg;
12881
12882 if (!BUFFERP (echo_area_buffer[0]))
12883 msg = Qnil;
12884 else
12885 {
12886 with_echo_area_buffer (0, 0, current_message_1, &msg, Qnil);
12887 if (NILP (msg))
12888 echo_area_buffer[0] = Qnil;
12889 }
12890
12891 return msg;
12892 }
12893
12894
12895 static bool
12896 current_message_1 (void *a1, Lisp_Object a2)
12897 {
12898 Lisp_Object *msg = a1;
12899
12900 if (Z > BEG)
12901 *msg = make_buffer_string (BEG, Z, true);
12902 else
12903 *msg = Qnil;
12904 return false;
12905 }
12906
12907
12908
12909
12910
12911
12912
12913 bool
12914 push_message (void)
12915 {
12916 Lisp_Object msg = current_message ();
12917 Vmessage_stack = Fcons (msg, Vmessage_stack);
12918 return STRINGP (msg);
12919 }
12920
12921
12922
12923
12924 void
12925 restore_message (void)
12926 {
12927 eassert (CONSP (Vmessage_stack));
12928 message3_nolog (XCAR (Vmessage_stack));
12929 }
12930
12931
12932
12933
12934 void
12935 pop_message_unwind (void)
12936 {
12937
12938 eassert (CONSP (Vmessage_stack));
12939 Vmessage_stack = XCDR (Vmessage_stack);
12940 }
12941
12942
12943
12944
12945
12946
12947 void
12948 check_message_stack (void)
12949 {
12950 if (!NILP (Vmessage_stack))
12951 emacs_abort ();
12952 }
12953
12954 void
12955 clear_message_stack (void)
12956 {
12957 Vmessage_stack = Qnil;
12958 }
12959
12960
12961
12962
12963 void
12964 truncate_echo_area (ptrdiff_t nchars)
12965 {
12966 if (nchars == 0)
12967 echo_area_buffer[0] = Qnil;
12968 else if (!noninteractive
12969 && INTERACTIVE
12970 && !NILP (echo_area_buffer[0]))
12971 {
12972 struct frame *sf = SELECTED_FRAME ();
12973
12974
12975
12976 if (sf->glyphs_initialized_p)
12977 with_echo_area_buffer (0, 0, truncate_message_1,
12978 (void *) (intptr_t) nchars, Qnil);
12979 }
12980 }
12981
12982
12983
12984
12985
12986 static bool
12987 truncate_message_1 (void *a1, Lisp_Object a2)
12988 {
12989 intptr_t nchars = (intptr_t) a1;
12990 if (BEG + nchars < Z)
12991 del_range (BEG + nchars, Z);
12992 if (Z == BEG)
12993 echo_area_buffer[0] = Qnil;
12994 return false;
12995 }
12996
12997 extern intptr_t garbage_collection_inhibited;
12998
12999
13000
13001 static void
13002 set_message (Lisp_Object string)
13003 {
13004 Lisp_Object message = Qnil;
13005
13006 eassert (STRINGP (string));
13007
13008 if (FUNCTIONP (Vset_message_function)
13009
13010
13011
13012 && !garbage_collection_inhibited)
13013 {
13014 specpdl_ref count = SPECPDL_INDEX ();
13015 specbind (Qinhibit_quit, Qt);
13016 message = safe_call1 (Vset_message_function, string);
13017 unbind_to (count, Qnil);
13018
13019 if (STRINGP (message))
13020 {
13021 string = message;
13022 message = Qnil;
13023 }
13024 }
13025
13026 if (NILP (message))
13027 {
13028 message_enable_multibyte = STRING_MULTIBYTE (string);
13029
13030 with_echo_area_buffer (0, -1, set_message_1, 0, string);
13031 message_buf_print = false;
13032 help_echo_showing_p = false;
13033 }
13034
13035 if (STRINGP (Vdebug_on_message)
13036 && STRINGP (string)
13037 && fast_string_match (Vdebug_on_message, string) >= 0)
13038 call_debugger (list2 (Qerror, string));
13039 }
13040
13041
13042
13043
13044
13045
13046 static bool
13047 set_message_1 (void *a1, Lisp_Object string)
13048 {
13049 eassert (STRINGP (string));
13050
13051
13052
13053
13054
13055
13056 if (!message_enable_multibyte
13057 && unibyte_display_via_language_environment
13058 && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
13059 Fset_buffer_multibyte (Qnil);
13060 else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
13061 Fset_buffer_multibyte (Qt);
13062
13063 bset_truncate_lines (current_buffer, message_truncate_lines ? Qt : Qnil);
13064 if (!NILP (BVAR (current_buffer, bidi_display_reordering)))
13065 bset_bidi_paragraph_direction (current_buffer, Qleft_to_right);
13066
13067
13068 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
13069
13070
13071
13072
13073 insert_from_string (string, 0, 0, SCHARS (string), SBYTES (string), true);
13074
13075 return false;
13076 }
13077
13078
13079
13080
13081
13082 void
13083 clear_message (bool current_p, bool last_displayed_p)
13084 {
13085 Lisp_Object preserve = Qnil;
13086
13087 if (current_p)
13088 {
13089 if (FUNCTIONP (Vclear_message_function)
13090
13091 && !garbage_collection_inhibited)
13092 {
13093 specpdl_ref count = SPECPDL_INDEX ();
13094 specbind (Qinhibit_quit, Qt);
13095 preserve = safe_call (1, Vclear_message_function);
13096 unbind_to (count, Qnil);
13097 }
13098
13099 if (!EQ (preserve, Qdont_clear_message))
13100 {
13101 echo_area_buffer[0] = Qnil;
13102 message_cleared_p = true;
13103 }
13104 }
13105
13106 if (last_displayed_p)
13107 echo_area_buffer[1] = Qnil;
13108
13109 message_buf_print = false;
13110 }
13111
13112
13113
13114
13115
13116
13117
13118
13119
13120
13121 static void
13122 clear_garbaged_frames (void)
13123 {
13124 if (frame_garbaged)
13125 {
13126 Lisp_Object tail, frame;
13127 struct frame *sf = SELECTED_FRAME ();
13128
13129 FOR_EACH_FRAME (tail, frame)
13130 {
13131 struct frame *f = XFRAME (frame);
13132
13133 if (FRAME_REDISPLAY_P (f) && FRAME_GARBAGED_P (f))
13134 {
13135 if (f->resized_p
13136
13137
13138
13139
13140
13141 && !(f != sf && (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))))
13142 redraw_frame (f);
13143 else
13144 clear_current_matrices (f);
13145
13146 #ifdef HAVE_WINDOW_SYSTEM
13147 if (FRAME_WINDOW_P (f)
13148 && FRAME_RIF (f)->clear_under_internal_border)
13149 FRAME_RIF (f)->clear_under_internal_border (f);
13150 #endif
13151 fset_redisplay (f);
13152 f->garbaged = false;
13153 f->resized_p = false;
13154 }
13155 }
13156
13157 frame_garbaged = false;
13158 }
13159 }
13160
13161
13162
13163
13164
13165 static void
13166 echo_area_display (bool update_frame_p)
13167 {
13168 Lisp_Object mini_window;
13169 struct window *w;
13170 struct frame *f;
13171 bool window_height_changed_p = false;
13172 struct frame *sf = SELECTED_FRAME ();
13173
13174 mini_window = FRAME_MINIBUF_WINDOW (sf);
13175 if (NILP (mini_window))
13176 return;
13177
13178 w = XWINDOW (mini_window);
13179 f = XFRAME (WINDOW_FRAME (w));
13180
13181
13182 if (!FRAME_REDISPLAY_P (f) || !f->glyphs_initialized_p)
13183 return;
13184
13185 #ifdef HAVE_WINDOW_SYSTEM
13186
13187
13188
13189 if (FRAME_INITIAL_P (XFRAME (selected_frame)))
13190 return;
13191 #endif
13192
13193
13194 clear_garbaged_frames ();
13195
13196 if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
13197 {
13198 echo_area_window = mini_window;
13199 window_height_changed_p = display_echo_area (w);
13200 w->must_be_updated_p = true;
13201
13202
13203
13204
13205
13206 if (update_frame_p && !redisplaying_p)
13207 {
13208 int n = 0;
13209
13210
13211
13212
13213
13214
13215 if (!display_completed)
13216 {
13217 n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), false);
13218
13219 #ifdef HAVE_WINDOW_SYSTEM
13220 if (FRAME_WINDOW_P (f)
13221 && FRAME_RIF (f)->clear_under_internal_border)
13222 FRAME_RIF (f)->clear_under_internal_border (f);
13223 #endif
13224 }
13225
13226 if (window_height_changed_p
13227
13228
13229 && !NILP (Vrun_hooks))
13230 {
13231
13232
13233
13234 specpdl_ref count = SPECPDL_INDEX ();
13235 specbind (Qredisplay_dont_pause, Qt);
13236 fset_redisplay (f);
13237 redisplay_internal ();
13238 unbind_to (count, Qnil);
13239 }
13240 else if (FRAME_WINDOW_P (f) && n == 0)
13241 {
13242
13243
13244
13245 update_single_window (w);
13246 flush_frame (f);
13247 }
13248 else
13249 update_frame (f, true, true);
13250
13251
13252
13253
13254 if (cursor_in_echo_area)
13255 wset_redisplay (XWINDOW (mini_window));
13256 }
13257 }
13258 else if (!EQ (mini_window, selected_window))
13259 wset_redisplay (XWINDOW (mini_window));
13260
13261
13262 echo_area_buffer[1] = echo_area_buffer[0];
13263
13264 echo_message_buffer = Qnil;
13265
13266
13267
13268
13269 if (EQ (mini_window, selected_window))
13270 CHARPOS (this_line_start_pos) = 0;
13271
13272 if (window_height_changed_p)
13273 {
13274 fset_redisplay (f);
13275
13276
13277
13278
13279
13280 clear_garbaged_frames ();
13281 }
13282 }
13283
13284
13285
13286 static bool
13287 window_buffer_changed (struct window *w)
13288 {
13289 struct buffer *b = XBUFFER (w->contents);
13290
13291 eassert (BUFFER_LIVE_P (b));
13292
13293 return (BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star;
13294 }
13295
13296
13297
13298 static bool
13299 mode_line_update_needed (struct window *w)
13300 {
13301 return (w->column_number_displayed != -1
13302 && !(PT == w->last_point && !window_outdated (w))
13303 && (w->column_number_displayed != current_column ()));
13304 }
13305
13306
13307
13308
13309 static bool
13310 window_frozen_p (struct window *w)
13311 {
13312 if (FRAME_WINDOWS_FROZEN (XFRAME (WINDOW_FRAME (w))))
13313 {
13314 Lisp_Object window;
13315
13316 XSETWINDOW (window, w);
13317 if (MINI_WINDOW_P (w))
13318 return false;
13319 else if (EQ (window, selected_window))
13320 return false;
13321 else if (MINI_WINDOW_P (XWINDOW (selected_window))
13322 && EQ (window, Vminibuf_scroll_window))
13323
13324 return false;
13325 else
13326 return true;
13327 }
13328 return false;
13329 }
13330
13331
13332
13333
13334
13335
13336
13337
13338
13339 static char *mode_line_noprop_buf;
13340
13341
13342
13343 static char *mode_line_noprop_buf_end;
13344 static char *mode_line_noprop_ptr;
13345
13346 #define MODE_LINE_NOPROP_LEN(start) \
13347 ((mode_line_noprop_ptr - mode_line_noprop_buf) - start)
13348
13349 static enum {
13350 MODE_LINE_DISPLAY = 0,
13351 MODE_LINE_TITLE,
13352 MODE_LINE_NOPROP,
13353 MODE_LINE_STRING
13354 } mode_line_target;
13355
13356
13357
13358 static Lisp_Object mode_line_proptrans_alist;
13359
13360
13361 static Lisp_Object mode_line_string_list;
13362
13363
13364 static Lisp_Object mode_line_string_face;
13365 static Lisp_Object mode_line_string_face_prop;
13366
13367
13368
13369
13370 static Lisp_Object Vmode_line_unwind_vector;
13371
13372 static Lisp_Object
13373 format_mode_line_unwind_data (struct frame *target_frame,
13374 struct buffer *obuf,
13375 Lisp_Object owin,
13376 bool save_proptrans)
13377 {
13378 Lisp_Object vector, tmp;
13379
13380
13381
13382 vector = Vmode_line_unwind_vector;
13383 Vmode_line_unwind_vector = Qnil;
13384
13385 if (NILP (vector))
13386 vector = make_nil_vector (12);
13387
13388 ASET (vector, 0, make_fixnum (mode_line_target));
13389 ASET (vector, 1, make_fixnum (MODE_LINE_NOPROP_LEN (0)));
13390 ASET (vector, 2, mode_line_string_list);
13391 ASET (vector, 3, save_proptrans ? mode_line_proptrans_alist : Qt);
13392 ASET (vector, 4, mode_line_string_face);
13393 ASET (vector, 5, mode_line_string_face_prop);
13394
13395 if (obuf)
13396 XSETBUFFER (tmp, obuf);
13397 else
13398 tmp = Qnil;
13399 ASET (vector, 6, tmp);
13400 ASET (vector, 7, owin);
13401 if (target_frame)
13402 {
13403 Lisp_Object buffer = XWINDOW (target_frame->selected_window)->contents;
13404 struct buffer *b = XBUFFER (buffer);
13405 struct buffer *cb = current_buffer;
13406
13407
13408
13409
13410 ASET (vector, 8, target_frame->selected_window);
13411 if (FRAME_TERMCAP_P (target_frame))
13412 ASET (vector, 9, FRAME_TTY (target_frame)->top_frame);
13413
13414
13415
13416
13417 ASET (vector, 10, buffer);
13418 current_buffer = b;
13419 ASET (vector, 11, build_marker (current_buffer, PT, PT_BYTE));
13420 current_buffer = cb;
13421 }
13422
13423 return vector;
13424 }
13425
13426 static void
13427 unwind_format_mode_line (Lisp_Object vector)
13428 {
13429 Lisp_Object old_window = AREF (vector, 7);
13430 Lisp_Object target_frame_window = AREF (vector, 8);
13431 Lisp_Object old_top_frame = AREF (vector, 9);
13432
13433 mode_line_target = XFIXNUM (AREF (vector, 0));
13434 mode_line_noprop_ptr = mode_line_noprop_buf + XFIXNUM (AREF (vector, 1));
13435 mode_line_string_list = AREF (vector, 2);
13436 if (! EQ (AREF (vector, 3), Qt))
13437 mode_line_proptrans_alist = AREF (vector, 3);
13438 mode_line_string_face = AREF (vector, 4);
13439 mode_line_string_face_prop = AREF (vector, 5);
13440
13441
13442 if (WINDOW_LIVE_P (old_window))
13443 {
13444
13445
13446
13447 if (WINDOW_LIVE_P (target_frame_window))
13448 {
13449 Lisp_Object frame
13450 = WINDOW_FRAME (XWINDOW (target_frame_window));
13451
13452 if (!EQ (frame, WINDOW_FRAME (XWINDOW (old_window))))
13453 Fselect_window (target_frame_window, Qt);
13454
13455 if (!NILP (old_top_frame) && !EQ (old_top_frame, frame)
13456
13457
13458 && FRAME_LIVE_P (XFRAME (old_top_frame)))
13459 Fselect_frame (old_top_frame, Qt);
13460 }
13461
13462 Fselect_window (old_window, Qt);
13463
13464
13465
13466
13467 if (WINDOW_LIVE_P (target_frame_window))
13468 {
13469 Lisp_Object buffer = AREF (vector, 10);
13470
13471 if (BUFFER_LIVE_P (XBUFFER (buffer)))
13472 {
13473 struct buffer *cb = current_buffer;
13474
13475 current_buffer = XBUFFER (buffer);
13476 set_point_from_marker (AREF (vector, 11));
13477 ASET (vector, 11, Qnil);
13478 current_buffer = cb;
13479 }
13480 }
13481 }
13482
13483 if (!NILP (AREF (vector, 6)))
13484 {
13485 set_buffer_internal_1 (XBUFFER (AREF (vector, 6)));
13486 ASET (vector, 6, Qnil);
13487 }
13488
13489 Vmode_line_unwind_vector = vector;
13490 }
13491
13492
13493
13494
13495
13496 static void
13497 store_mode_line_noprop_char (char c)
13498 {
13499
13500
13501 if (mode_line_noprop_ptr == mode_line_noprop_buf_end)
13502 {
13503 ptrdiff_t len = MODE_LINE_NOPROP_LEN (0);
13504 ptrdiff_t size = len;
13505 mode_line_noprop_buf =
13506 xpalloc (mode_line_noprop_buf, &size, 1, STRING_BYTES_BOUND, 1);
13507 mode_line_noprop_buf_end = mode_line_noprop_buf + size;
13508 mode_line_noprop_ptr = mode_line_noprop_buf + len;
13509 }
13510
13511 *mode_line_noprop_ptr++ = c;
13512 }
13513
13514
13515
13516
13517
13518
13519
13520
13521
13522
13523 static int
13524 store_mode_line_noprop (const char *string, int field_width, int precision)
13525 {
13526 const unsigned char *str = (const unsigned char *) string;
13527 int n = 0;
13528 ptrdiff_t dummy, nbytes;
13529
13530
13531 nbytes = strlen (string);
13532 n += c_string_width (str, nbytes, precision, &dummy, &nbytes);
13533 while (nbytes--)
13534 store_mode_line_noprop_char (*str++);
13535
13536
13537 while (field_width > 0
13538 && n < field_width)
13539 {
13540 store_mode_line_noprop_char (' ');
13541 ++n;
13542 }
13543
13544 return n;
13545 }
13546
13547
13548
13549
13550
13551 #ifdef HAVE_WINDOW_SYSTEM
13552
13553
13554
13555
13556
13557 void
13558 gui_consider_frame_title (Lisp_Object frame)
13559 {
13560 struct frame *f = XFRAME (frame);
13561 Lisp_Object format_data;
13562
13563 if ((FRAME_WINDOW_P (f)
13564 || FRAME_MINIBUF_ONLY_P (f)
13565 || f->explicit_name)
13566 && !FRAME_TOOLTIP_P (f))
13567 {
13568
13569 Lisp_Object tail, other_frame, fmt;
13570 ptrdiff_t title_start;
13571 char *title;
13572 ptrdiff_t len;
13573 struct it it;
13574 specpdl_ref count = SPECPDL_INDEX ();
13575
13576 FOR_EACH_FRAME (tail, other_frame)
13577 {
13578 struct frame *tf = XFRAME (other_frame);
13579
13580 if (tf != f
13581 && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
13582 && !FRAME_MINIBUF_ONLY_P (tf)
13583 && !FRAME_PARENT_FRAME (tf)
13584 && !FRAME_TOOLTIP_P (tf)
13585 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
13586 break;
13587 }
13588
13589
13590 multiple_frames = CONSP (tail);
13591
13592
13593
13594
13595
13596
13597
13598
13599
13600
13601
13602
13603 specbind (Qinhibit_redisplay, Qt);
13604
13605
13606
13607
13608
13609
13610
13611
13612 format_data = format_mode_line_unwind_data (f, current_buffer,
13613 selected_window,
13614 false);
13615 record_unwind_protect (unwind_format_mode_line, format_data);
13616
13617 Fselect_window (f->selected_window, Qt);
13618 set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->contents));
13619 fmt = (FRAME_ICONIFIED_P (f) && !EQ (Vicon_title_format, Qt)
13620 ? Vicon_title_format : Vframe_title_format);
13621
13622 mode_line_target = MODE_LINE_TITLE;
13623 title_start = MODE_LINE_NOPROP_LEN (0);
13624 init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
13625 NULL, DEFAULT_FACE_ID);
13626 display_mode_element (&it, 0, -1, -1, fmt, Qnil, false);
13627 len = MODE_LINE_NOPROP_LEN (title_start);
13628 title = mode_line_noprop_buf + title_start;
13629
13630
13631 ptrdiff_t nchars = 0;
13632 len = str_as_multibyte ((unsigned char *) title,
13633 mode_line_noprop_buf_end - title,
13634 len, &nchars);
13635 unbind_to (count, Qnil);
13636
13637
13638
13639
13640
13641
13642 if ((! STRINGP (f->name)
13643 || SBYTES (f->name) != len
13644 || memcmp (title, SDATA (f->name), len) != 0)
13645 && FRAME_TERMINAL (f)->implicit_set_name_hook)
13646 {
13647 Lisp_Object title_string = make_multibyte_string (title, nchars, len);
13648 FRAME_TERMINAL (f)->implicit_set_name_hook (f, title_string, Qnil);
13649 }
13650 }
13651 }
13652
13653 #endif
13654
13655
13656
13657
13658
13659
13660
13661 #define REDISPLAY_SOME_P() \
13662 ((windows_or_buffers_changed == 0 \
13663 || windows_or_buffers_changed == REDISPLAY_SOME) \
13664 && (update_mode_lines == 0 \
13665 || update_mode_lines == REDISPLAY_SOME))
13666
13667 static bool
13668 needs_no_redisplay (struct window *w)
13669 {
13670 struct buffer *buffer = XBUFFER (w->contents);
13671 struct frame *f = XFRAME (w->frame);
13672 return (REDISPLAY_SOME_P ()
13673 && !w->redisplay
13674 && !w->update_mode_line
13675 && !f->face_change
13676 && !f->redisplay
13677 && !buffer->text->redisplay
13678 && window_point (w) == w->last_point);
13679 }
13680
13681
13682
13683
13684 static void
13685 prepare_menu_bars (void)
13686 {
13687 bool all_windows = windows_or_buffers_changed || update_mode_lines;
13688 bool some_windows = REDISPLAY_SOME_P ();
13689
13690 if (FUNCTIONP (Vpre_redisplay_function))
13691 {
13692 Lisp_Object windows = all_windows ? Qt : Qnil;
13693 if (all_windows && some_windows)
13694 {
13695 Lisp_Object ws = window_list ();
13696 for (windows = Qnil; CONSP (ws); ws = XCDR (ws))
13697 {
13698 Lisp_Object this = XCAR (ws);
13699 struct window *w = XWINDOW (this);
13700
13701
13702 if (!needs_no_redisplay (w))
13703 windows = Fcons (this, windows);
13704 }
13705 }
13706 safe__call1 (true, Vpre_redisplay_function, windows);
13707 }
13708
13709
13710
13711
13712 #ifdef HAVE_WINDOW_SYSTEM
13713 if (all_windows)
13714 {
13715 Lisp_Object tail, frame;
13716
13717 FOR_EACH_FRAME (tail, frame)
13718 {
13719 struct frame *f = XFRAME (frame);
13720 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
13721 if (some_windows
13722 && !f->redisplay
13723 && !w->redisplay
13724 && !XBUFFER (w->contents)->text->redisplay)
13725 continue;
13726
13727 if (!FRAME_TOOLTIP_P (f)
13728 && (FRAME_ICONIFIED_P (f)
13729 || FRAME_VISIBLE_P (f) == 1
13730
13731
13732
13733
13734
13735
13736
13737
13738
13739 || (FRAME_REDISPLAY_P (f) && FRAME_WINDOW_P (f))))
13740 gui_consider_frame_title (frame);
13741 }
13742 }
13743 #endif
13744
13745
13746
13747
13748 if (all_windows)
13749 {
13750 Lisp_Object tail, frame;
13751 specpdl_ref count = SPECPDL_INDEX ();
13752
13753
13754 bool menu_bar_hooks_run = false;
13755
13756 record_unwind_save_match_data ();
13757
13758 FOR_EACH_FRAME (tail, frame)
13759 {
13760 struct frame *f = XFRAME (frame);
13761 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
13762
13763
13764 if (FRAME_TOOLTIP_P (f))
13765 continue;
13766
13767 if (some_windows
13768 && !f->redisplay
13769 && !w->redisplay
13770 && !XBUFFER (w->contents)->text->redisplay)
13771 continue;
13772
13773 if (!FRAME_PARENT_FRAME (f))
13774 menu_bar_hooks_run = update_menu_bar (f, false, menu_bar_hooks_run);
13775
13776 update_tab_bar (f, false);
13777 #ifdef HAVE_WINDOW_SYSTEM
13778 update_tool_bar (f, false);
13779 #endif
13780 }
13781
13782 unbind_to (count, Qnil);
13783 }
13784 else
13785 {
13786 struct frame *sf = SELECTED_FRAME ();
13787
13788 if (!FRAME_PARENT_FRAME (sf))
13789 update_menu_bar (sf, true, false);
13790
13791 update_tab_bar (sf, true);
13792 #ifdef HAVE_WINDOW_SYSTEM
13793 update_tool_bar (sf, true);
13794 #endif
13795 }
13796 }
13797
13798
13799
13800
13801
13802
13803
13804
13805
13806
13807
13808
13809
13810 static bool
13811 update_menu_bar (struct frame *f, bool save_match_data, bool hooks_run)
13812 {
13813 Lisp_Object window;
13814 struct window *w;
13815
13816
13817
13818
13819 if (inhibit_menubar_update)
13820 return hooks_run;
13821
13822 window = FRAME_SELECTED_WINDOW (f);
13823 w = XWINDOW (window);
13824
13825 if (FRAME_WINDOW_P (f)
13826 ?
13827 #ifdef HAVE_EXT_MENU_BAR
13828 FRAME_EXTERNAL_MENU_BAR (f)
13829 #else
13830 FRAME_MENU_BAR_LINES (f) > 0
13831 #endif
13832 : FRAME_MENU_BAR_LINES (f) > 0)
13833 {
13834
13835
13836
13837
13838
13839
13840
13841 if (windows_or_buffers_changed
13842
13843
13844 || update_mode_lines
13845 || window_buffer_changed (w))
13846 {
13847 struct buffer *prev = current_buffer;
13848 specpdl_ref count = SPECPDL_INDEX ();
13849
13850 specbind (Qinhibit_menubar_update, Qt);
13851
13852 set_buffer_internal_1 (XBUFFER (w->contents));
13853 if (save_match_data)
13854 record_unwind_save_match_data ();
13855 if (NILP (Voverriding_local_map_menu_flag))
13856 {
13857 specbind (Qoverriding_terminal_local_map, Qnil);
13858 specbind (Qoverriding_local_map, Qnil);
13859 }
13860
13861 if (!hooks_run)
13862 {
13863
13864 safe_run_hooks (Qactivate_menubar_hook);
13865
13866
13867
13868 safe_run_hooks (Qmenu_bar_update_hook);
13869
13870 hooks_run = true;
13871 }
13872
13873 XSETFRAME (Vmenu_updating_frame, f);
13874 fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
13875
13876
13877 #ifdef HAVE_EXT_MENU_BAR
13878 if (FRAME_WINDOW_P (f))
13879 {
13880 #if defined (HAVE_NS)
13881
13882
13883 if (f == SELECTED_FRAME ())
13884 #endif
13885 set_frame_menubar (f, false);
13886 }
13887 else
13888
13889
13890 w->update_mode_line = true;
13891 #else
13892
13893
13894 w->update_mode_line = true;
13895 #endif
13896
13897 unbind_to (count, Qnil);
13898 set_buffer_internal_1 (prev);
13899 }
13900 }
13901
13902 return hooks_run;
13903 }
13904
13905
13906
13907
13908
13909
13910
13911
13912
13913
13914
13915
13916 static void
13917 restore_selected_window (Lisp_Object window)
13918 {
13919 if (WINDOW_LIVE_P (window))
13920
13921
13922 {
13923 selected_window = window;
13924 selected_frame = XWINDOW (window)->frame;
13925 FRAME_SELECTED_WINDOW (XFRAME (selected_frame)) = window;
13926 }
13927 else if (FRAMEP (selected_frame) && FRAME_LIVE_P (XFRAME (selected_frame)))
13928
13929
13930 selected_window = FRAME_SELECTED_WINDOW (XFRAME (selected_frame));
13931 else
13932
13933
13934
13935 {
13936 Lisp_Object tail;
13937 Lisp_Object frame UNINIT;
13938
13939 FOR_EACH_FRAME (tail, frame)
13940 {
13941 struct frame *f = XFRAME (frame);
13942
13943 if (!FRAME_PARENT_FRAME (f) && !FRAME_TOOLTIP_P (f))
13944 {
13945 selected_frame = frame;
13946 selected_window = FRAME_SELECTED_WINDOW (f);
13947
13948 return;
13949 }
13950 }
13951
13952
13953 emacs_abort ();
13954 }
13955 }
13956
13957
13958 static void
13959 restore_frame_selected_window (Lisp_Object window)
13960 {
13961 if (WINDOW_LIVE_P (window))
13962
13963
13964
13965 {
13966 Lisp_Object frame = XWINDOW (window)->frame;
13967
13968 FRAME_SELECTED_WINDOW (XFRAME (frame)) = window;
13969 if (EQ (frame, selected_frame))
13970 selected_window = window;
13971 }
13972 }
13973
13974
13975
13976
13977
13978
13979 static void
13980 update_tab_bar (struct frame *f, bool save_match_data)
13981 {
13982 bool do_update = false;
13983
13984 #ifdef HAVE_WINDOW_SYSTEM
13985 if (FRAME_WINDOW_P (f) && WINDOWP (f->tab_bar_window)) {
13986 if (WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)) > 0)
13987 do_update = true;
13988 }
13989 else
13990 #endif
13991 if (FRAME_TAB_BAR_LINES (f) > 0)
13992 do_update = true;
13993
13994 if (do_update)
13995 {
13996 Lisp_Object window;
13997 struct window *w;
13998
13999 window = FRAME_SELECTED_WINDOW (f);
14000 w = XWINDOW (window);
14001
14002
14003
14004
14005
14006
14007
14008
14009 if (windows_or_buffers_changed
14010 || w->update_mode_line
14011 || update_mode_lines
14012 || window_buffer_changed (w))
14013 {
14014 struct buffer *prev = current_buffer;
14015 specpdl_ref count = SPECPDL_INDEX ();
14016 Lisp_Object new_tab_bar;
14017 int new_n_tab_bar;
14018
14019
14020
14021
14022 set_buffer_internal_1 (XBUFFER (w->contents));
14023
14024
14025 if (save_match_data)
14026 record_unwind_save_match_data ();
14027
14028
14029 if (NILP (Voverriding_local_map_menu_flag))
14030 {
14031 specbind (Qoverriding_terminal_local_map, Qnil);
14032 specbind (Qoverriding_local_map, Qnil);
14033 }
14034
14035
14036
14037
14038
14039 eassert (EQ (selected_window,
14040
14041
14042 XFRAME (selected_frame)->selected_window));
14043 #ifdef HAVE_WINDOW_SYSTEM
14044 Lisp_Object frame;
14045 record_unwind_protect (restore_selected_window, selected_window);
14046 XSETFRAME (frame, f);
14047 selected_frame = frame;
14048 selected_window = FRAME_SELECTED_WINDOW (f);
14049 #endif
14050
14051
14052 new_tab_bar
14053 = tab_bar_items (Fcopy_sequence (f->tab_bar_items),
14054 &new_n_tab_bar);
14055
14056
14057 if (new_n_tab_bar != f->n_tab_bar_items
14058 || NILP (Fequal (new_tab_bar, f->tab_bar_items)))
14059 {
14060
14061
14062
14063 block_input ();
14064 fset_tab_bar_items (f, new_tab_bar);
14065 f->n_tab_bar_items = new_n_tab_bar;
14066 w->update_mode_line = true;
14067 unblock_input ();
14068 }
14069
14070 unbind_to (count, Qnil);
14071 set_buffer_internal_1 (prev);
14072 }
14073 }
14074 }
14075
14076
14077
14078
14079
14080
14081
14082
14083
14084
14085
14086 static void
14087 display_tab_bar (struct window *w)
14088 {
14089 struct frame *f = XFRAME (WINDOW_FRAME (w));
14090 struct it it;
14091 Lisp_Object items;
14092 int i;
14093
14094
14095 #ifdef HAVE_NTGUI
14096 if (FRAME_W32_P (f))
14097 return;
14098 #endif
14099 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
14100 if (FRAME_X_P (f))
14101 return;
14102 #endif
14103
14104 #ifdef HAVE_NS
14105 if (FRAME_NS_P (f))
14106 return;
14107 #endif
14108
14109 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
14110 eassert (!FRAME_WINDOW_P (f));
14111 init_iterator (&it, w, -1, -1, f->desired_matrix->rows
14112 + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0),
14113 TAB_BAR_FACE_ID);
14114 it.first_visible_x = 0;
14115 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
14116 #elif defined (HAVE_X_WINDOWS)
14117 if (FRAME_WINDOW_P (f))
14118 {
14119
14120
14121 struct window *tab_w;
14122 tab_w = XWINDOW (f->tab_bar_window);
14123 init_iterator (&it, tab_w, -1, -1, tab_w->desired_matrix->rows,
14124 TAB_BAR_FACE_ID);
14125 it.first_visible_x = 0;
14126 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
14127 }
14128 else
14129 #endif
14130 {
14131
14132
14133 init_iterator (&it, w, -1, -1, f->desired_matrix->rows
14134 + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0),
14135 TAB_BAR_FACE_ID);
14136 it.first_visible_x = 0;
14137 it.last_visible_x = FRAME_COLS (f);
14138 }
14139
14140
14141
14142
14143 it.paragraph_embedding = L2R;
14144
14145
14146 for (i = 0; i < FRAME_TAB_BAR_LINES (f); ++i)
14147 {
14148 struct glyph_row *row = it.glyph_row + i;
14149 clear_glyph_row (row);
14150 row->enabled_p = true;
14151 row->full_width_p = true;
14152 row->reversed_p = false;
14153 }
14154
14155
14156 items = it.f->tab_bar_items;
14157 int j;
14158 for (i = 0, j = 0; i < it.f->n_tab_bar_items; ++i, j += TAB_BAR_ITEM_NSLOTS)
14159 {
14160 Lisp_Object string = AREF (items, j + TAB_BAR_ITEM_CAPTION);
14161
14162
14163 if (NILP (string))
14164 break;
14165
14166 if (it.current_x < it.last_visible_x)
14167 display_string (NULL, string, Qnil, 0, 0, &it,
14168 SCHARS (string), 0, 0, STRING_MULTIBYTE (string));
14169 }
14170
14171
14172 if (it.current_x < it.last_visible_x)
14173 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
14174
14175
14176 compute_line_metrics (&it);
14177 }
14178
14179 #ifdef HAVE_WINDOW_SYSTEM
14180
14181
14182
14183
14184
14185 static void
14186 build_desired_tab_bar_string (struct frame *f)
14187 {
14188 int i;
14189 Lisp_Object caption;
14190
14191 caption = Qnil;
14192
14193
14194 fset_desired_tab_bar_string (f, build_string (""));
14195
14196
14197
14198
14199 for (i = 0; i < f->n_tab_bar_items; ++i)
14200 {
14201 #define PROP(IDX) \
14202 AREF (f->tab_bar_items, i * TAB_BAR_ITEM_NSLOTS + (IDX))
14203
14204 caption = Fcopy_sequence (PROP (TAB_BAR_ITEM_CAPTION));
14205
14206
14207
14208
14209
14210 AUTO_LIST2 (props, Qmenu_item, make_fixnum (i * TAB_BAR_ITEM_NSLOTS));
14211
14212 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14213 props, caption);
14214
14215 f->desired_tab_bar_string =
14216 concat2 (f->desired_tab_bar_string, caption);
14217
14218 #undef PROP
14219 }
14220 }
14221
14222
14223
14224
14225
14226
14227
14228
14229
14230
14231
14232
14233
14234
14235 static void
14236 display_tab_bar_line (struct it *it, int height)
14237 {
14238 struct glyph_row *row = it->glyph_row;
14239 int max_x = it->last_visible_x;
14240 struct glyph *last;
14241
14242
14243 clear_glyph_row (row);
14244 row->enabled_p = true;
14245 row->y = it->current_y;
14246
14247
14248
14249 it->start_of_box_run_p = true;
14250
14251 bool enough = false;
14252 while (it->current_x < max_x)
14253 {
14254 int x, n_glyphs_before, i, nglyphs;
14255 struct it it_before;
14256
14257
14258 if (!get_next_display_element (it))
14259 {
14260
14261 if (height < 0 && !it->hpos)
14262 return;
14263 break;
14264 }
14265
14266
14267 n_glyphs_before = row->used[TEXT_AREA];
14268 it_before = *it;
14269
14270 PRODUCE_GLYPHS (it);
14271
14272 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
14273 i = 0;
14274 x = it_before.current_x;
14275 while (i < nglyphs)
14276 {
14277 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
14278
14279 if (x + glyph->pixel_width > max_x)
14280 {
14281
14282 row->used[TEXT_AREA] = n_glyphs_before;
14283 *it = it_before;
14284
14285
14286
14287 if (n_glyphs_before == 0
14288 && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
14289 break;
14290 goto out;
14291 }
14292
14293 ++it->hpos;
14294 x += glyph->pixel_width;
14295 ++i;
14296 }
14297
14298 enough = ITERATOR_AT_END_OF_LINE_P (it);
14299 set_iterator_to_next (it, true);
14300
14301
14302 if (enough)
14303 break;
14304 }
14305
14306 out:;
14307
14308 row->displays_text_p = row->used[TEXT_AREA] != 0;
14309
14310
14311
14312
14313
14314
14315
14316 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
14317 && !EQ (Vauto_resize_tab_bars, Qgrow_only))
14318 it->face_id = DEFAULT_FACE_ID;
14319
14320 extend_face_to_end_of_line (it);
14321 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
14322 last->right_box_line_p = true;
14323 if (last == row->glyphs[TEXT_AREA])
14324 last->left_box_line_p = true;
14325
14326
14327 if ((height -= it->max_ascent + it->max_descent) > 0)
14328 {
14329
14330 height %= FRAME_LINE_HEIGHT (it->f);
14331 it->max_ascent += height / 2;
14332 it->max_descent += (height + 1) / 2;
14333 }
14334
14335 compute_line_metrics (it);
14336
14337
14338 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row))
14339 {
14340 row->height = row->phys_height = it->last_visible_y - row->y;
14341 row->visible_height = row->height;
14342 row->ascent = row->phys_ascent = 0;
14343 row->extra_line_spacing = 0;
14344 }
14345
14346 row->full_width_p = true;
14347 row->continued_p = false;
14348 row->truncated_on_left_p = false;
14349 row->truncated_on_right_p = false;
14350
14351 it->current_x = it->hpos = 0;
14352 it->current_y += row->height;
14353 ++it->vpos;
14354 ++it->glyph_row;
14355 }
14356
14357
14358
14359
14360
14361 static int
14362 tab_bar_height (struct frame *f, int *n_rows, bool pixelwise)
14363 {
14364 struct window *w = XWINDOW (f->tab_bar_window);
14365 struct it it;
14366
14367
14368
14369 struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
14370
14371
14372
14373 init_iterator (&it, w, -1, -1, temp_row, TAB_BAR_FACE_ID);
14374 temp_row->reversed_p = false;
14375 it.first_visible_x = 0;
14376 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
14377 reseat_to_string (&it, NULL, f->desired_tab_bar_string,
14378 0, 0, 0, STRING_MULTIBYTE (f->desired_tab_bar_string));
14379 it.paragraph_embedding = L2R;
14380
14381 clear_glyph_row (temp_row);
14382 while (!ITERATOR_AT_END_P (&it))
14383 {
14384 it.glyph_row = temp_row;
14385 display_tab_bar_line (&it, -1);
14386 }
14387 clear_glyph_row (temp_row);
14388
14389
14390 if (n_rows)
14391 *n_rows = it.vpos > 0 ? it.vpos : -1;
14392
14393 if (pixelwise)
14394 return it.current_y;
14395 else
14396 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
14397 }
14398
14399 DEFUN ("tab-bar-height", Ftab_bar_height, Stab_bar_height,
14400 0, 2, 0,
14401 doc:
14402
14403 )
14404 (Lisp_Object frame, Lisp_Object pixelwise)
14405 {
14406 int height = 0;
14407
14408 struct frame *f = decode_any_frame (frame);
14409
14410 if (WINDOWP (f->tab_bar_window)
14411 && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tab_bar_window)) > 0)
14412 {
14413 update_tab_bar (f, true);
14414 if (f->n_tab_bar_items)
14415 {
14416 build_desired_tab_bar_string (f);
14417 height = tab_bar_height (f, NULL, !NILP (pixelwise));
14418 }
14419 }
14420
14421 return make_fixnum (height);
14422 }
14423
14424
14425
14426
14427 static bool
14428 redisplay_tab_bar (struct frame *f)
14429 {
14430 struct window *w;
14431 struct it it;
14432 struct glyph_row *row;
14433
14434 f->tab_bar_redisplayed = true;
14435
14436
14437
14438
14439
14440 if (!WINDOWP (f->tab_bar_window)
14441 || (w = XWINDOW (f->tab_bar_window),
14442 WINDOW_TOTAL_LINES (w) == 0))
14443 {
14444
14445
14446
14447
14448
14449 f->tab_bar_resized = true;
14450
14451 return false;
14452 }
14453
14454
14455 build_desired_tab_bar_string (f);
14456
14457 int new_nrows;
14458 int new_height = tab_bar_height (f, &new_nrows, true);
14459
14460 if (f->n_tab_bar_rows == 0)
14461 {
14462 f->n_tab_bar_rows = new_nrows;
14463 if (new_height != WINDOW_PIXEL_HEIGHT (w))
14464 frame_default_tab_bar_height = new_height;
14465 }
14466
14467
14468
14469 if (new_nrows > f->n_tab_bar_rows
14470 || (EQ (Vauto_resize_tab_bars, Qgrow_only)
14471 && !f->minimize_tab_bar_window_p
14472 && new_height > WINDOW_PIXEL_HEIGHT (w))
14473 || (! EQ (Vauto_resize_tab_bars, Qgrow_only)
14474 && new_height < WINDOW_PIXEL_HEIGHT (w)))
14475 {
14476 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook)
14477 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height);
14478 if (new_nrows != f->n_tab_bar_rows)
14479 f->n_tab_bar_rows = new_nrows;
14480 clear_glyph_matrix (w->desired_matrix);
14481 f->fonts_changed = true;
14482 return true;
14483 }
14484
14485
14486 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TAB_BAR_FACE_ID);
14487 it.first_visible_x = 0;
14488 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
14489 row = it.glyph_row;
14490 row->reversed_p = false;
14491 reseat_to_string (&it, NULL, f->desired_tab_bar_string, 0, 0, 0,
14492 STRING_MULTIBYTE (f->desired_tab_bar_string));
14493
14494
14495
14496
14497
14498
14499
14500 it.paragraph_embedding = L2R;
14501
14502
14503
14504 if (f->n_tab_bar_rows > 0)
14505 {
14506 int border, rows, height, extra;
14507
14508 if (TYPE_RANGED_FIXNUMP (int, Vtab_bar_border))
14509 border = XFIXNUM (Vtab_bar_border);
14510 else if (EQ (Vtab_bar_border, Qinternal_border_width))
14511 border = FRAME_INTERNAL_BORDER_WIDTH (f);
14512 else if (EQ (Vtab_bar_border, Qborder_width))
14513 border = f->border_width;
14514 else
14515 border = 0;
14516 if (border < 0)
14517 border = 0;
14518
14519 rows = f->n_tab_bar_rows;
14520 height = max (1, (it.last_visible_y - border) / rows);
14521 extra = it.last_visible_y - border - height * rows;
14522
14523 while (it.current_y < it.last_visible_y)
14524 {
14525 int h = 0;
14526 if (extra > 0 && rows-- > 0)
14527 {
14528 h = (extra + rows - 1) / rows;
14529 extra -= h;
14530 }
14531 display_tab_bar_line (&it, height + h);
14532 }
14533 }
14534 else
14535 {
14536 while (it.current_y < it.last_visible_y)
14537 display_tab_bar_line (&it, 0);
14538 }
14539
14540
14541
14542 w->desired_matrix->no_scrolling_p = true;
14543 w->must_be_updated_p = true;
14544
14545 if (!NILP (Vauto_resize_tab_bars))
14546 {
14547 bool change_height_p = false;
14548
14549
14550
14551 if (IT_STRING_CHARPOS (it) < it.end_charpos)
14552 change_height_p = true;
14553
14554
14555
14556
14557
14558 row = it.glyph_row - 1;
14559
14560
14561
14562
14563 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
14564 && row->height >= FRAME_LINE_HEIGHT (f))
14565 change_height_p = true;
14566
14567
14568
14569 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
14570 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
14571 change_height_p = true;
14572
14573
14574
14575 if (change_height_p)
14576 {
14577 int nrows;
14578 int new_height = tab_bar_height (f, &nrows, true);
14579
14580 change_height_p = ((EQ (Vauto_resize_tab_bars, Qgrow_only)
14581 && !f->minimize_tab_bar_window_p)
14582 ? (new_height > WINDOW_PIXEL_HEIGHT (w))
14583 : (new_height != WINDOW_PIXEL_HEIGHT (w)));
14584 f->minimize_tab_bar_window_p = false;
14585
14586 if (change_height_p)
14587 {
14588 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook)
14589 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height);
14590 frame_default_tab_bar_height = new_height;
14591 clear_glyph_matrix (w->desired_matrix);
14592 f->n_tab_bar_rows = nrows;
14593 f->fonts_changed = true;
14594
14595 return true;
14596 }
14597 }
14598 }
14599
14600 f->minimize_tab_bar_window_p = false;
14601 return false;
14602 }
14603
14604
14605
14606
14607
14608
14609
14610 static bool
14611 tab_bar_item_info (struct frame *f, struct glyph *glyph,
14612 int *prop_idx, bool *close_p)
14613 {
14614 Lisp_Object prop;
14615 ptrdiff_t charpos;
14616
14617
14618
14619
14620 charpos = min (SCHARS (f->current_tab_bar_string), glyph->charpos);
14621 charpos = max (0, charpos);
14622
14623
14624
14625
14626 prop = Fget_text_property (make_fixnum (charpos),
14627 Qmenu_item, f->current_tab_bar_string);
14628 if (! FIXNUMP (prop))
14629 return false;
14630
14631 *prop_idx = XFIXNUM (prop);
14632
14633 if (close_p)
14634 *close_p = !NILP (Fget_text_property (make_fixnum (charpos),
14635 Qclose_tab,
14636 f->current_tab_bar_string));
14637
14638 return true;
14639 }
14640
14641
14642
14643
14644
14645
14646
14647
14648
14649
14650
14651
14652
14653
14654
14655
14656
14657
14658
14659
14660
14661 static int
14662 get_tab_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
14663 int *hpos, int *vpos, int *prop_idx, bool *close_p)
14664 {
14665 struct window *w = XWINDOW (f->tab_bar_window);
14666 int area;
14667
14668
14669 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
14670 if (*glyph == NULL)
14671 return -1;
14672
14673
14674
14675 if (!tab_bar_item_info (f, *glyph, prop_idx, close_p))
14676 return -1;
14677
14678 return *prop_idx == f->last_tab_bar_item ? 0 : 1;
14679 }
14680
14681
14682
14683
14684
14685
14686
14687 int
14688 get_tab_bar_item_kbd (struct frame *f, int x, int y, int *prop_idx,
14689 bool *close_p)
14690 {
14691 struct window *w;
14692 int area, vpos, hpos;
14693 struct glyph *glyph;
14694
14695 w = XWINDOW (f->tab_bar_window);
14696
14697
14698 frame_to_window_pixel_xy (w, &x, &y);
14699
14700
14701 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, 0,
14702 0, &area);
14703 if (glyph == NULL)
14704 return -1;
14705
14706
14707
14708 if (!tab_bar_item_info (f, glyph, prop_idx, close_p))
14709 return -1;
14710
14711 return *prop_idx == f->last_tab_bar_item ? 0 : 1;
14712 }
14713
14714
14715
14716
14717
14718
14719
14720 Lisp_Object
14721 handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
14722 int modifiers)
14723 {
14724 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
14725 struct window *w = XWINDOW (f->tab_bar_window);
14726 int hpos, vpos, prop_idx;
14727 bool close_p;
14728 struct glyph *glyph;
14729 Lisp_Object enabled_p;
14730 int ts;
14731
14732 frame_to_window_pixel_xy (w, &x, &y);
14733 ts = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
14734 if (ts == -1)
14735 return Fcons (Qtab_bar, Qnil);
14736
14737
14738 enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
14739 if (NILP (enabled_p))
14740 return Qnil;
14741
14742 if (down_p)
14743 {
14744
14745 if (!NILP (Vmouse_highlight))
14746 show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
14747 f->last_tab_bar_item = prop_idx;
14748 }
14749 else
14750 {
14751
14752 if (!NILP (Vmouse_highlight))
14753 show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
14754 f->last_tab_bar_item = -1;
14755 }
14756
14757 Lisp_Object caption =
14758 Fcopy_sequence (AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION));
14759
14760 AUTO_LIST2 (props, Qmenu_item,
14761 list3 (AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_KEY),
14762 AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_BINDING),
14763 close_p ? Qt : Qnil));
14764
14765 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14766 props, caption);
14767
14768 return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0)));
14769 }
14770
14771
14772
14773
14774
14775
14776 static void
14777 note_tab_bar_highlight (struct frame *f, int x, int y)
14778 {
14779 Lisp_Object window = f->tab_bar_window;
14780 struct window *w = XWINDOW (window);
14781 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
14782 int hpos, vpos;
14783 struct glyph *glyph;
14784 struct glyph_row *row;
14785 int i;
14786 Lisp_Object enabled_p;
14787 int prop_idx;
14788 bool close_p;
14789 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
14790 int rc;
14791
14792
14793
14794 if (x <= 0 || y <= 0)
14795 {
14796 clear_mouse_face (hlinfo);
14797 return;
14798 }
14799
14800 rc = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
14801 if (rc < 0)
14802 {
14803
14804 clear_mouse_face (hlinfo);
14805 return;
14806 }
14807 else if (rc == 0)
14808
14809 goto set_help_echo;
14810
14811 clear_mouse_face (hlinfo);
14812
14813 bool mouse_down_p = false;
14814
14815
14816
14817
14818
14819 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
14820 mouse_down_p = (gui_mouse_grabbed (dpyinfo)
14821 && f == dpyinfo->last_mouse_frame);
14822
14823 if (mouse_down_p && f->last_tab_bar_item != prop_idx
14824 && f->last_tab_bar_item != -1)
14825 return;
14826 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
14827
14828
14829 enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
14830 if (!NILP (enabled_p) && !NILP (Vmouse_highlight))
14831 {
14832
14833
14834 row = MATRIX_ROW (w->current_matrix, vpos);
14835 for (i = x = 0; i < hpos; ++i)
14836 x += row->glyphs[TEXT_AREA][i].pixel_width;
14837
14838
14839 hlinfo->mouse_face_beg_col = hpos;
14840 hlinfo->mouse_face_beg_row = vpos;
14841 hlinfo->mouse_face_beg_x = x;
14842 hlinfo->mouse_face_past_end = false;
14843
14844 hlinfo->mouse_face_end_col = hpos + 1;
14845 hlinfo->mouse_face_end_row = vpos;
14846 hlinfo->mouse_face_end_x = x + glyph->pixel_width;
14847 hlinfo->mouse_face_window = window;
14848 hlinfo->mouse_face_face_id = TAB_BAR_FACE_ID;
14849
14850
14851 show_mouse_face (hlinfo, draw);
14852 }
14853
14854 set_help_echo:
14855
14856
14857
14858 help_echo_object = help_echo_window = Qnil;
14859 help_echo_pos = -1;
14860 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_HELP);
14861 if (NILP (help_echo_string))
14862 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION);
14863 }
14864
14865 #endif
14866
14867
14868 static Lisp_Object
14869 tty_get_tab_bar_item (struct frame *f, int x, int *prop_idx, bool *close_p)
14870 {
14871 ptrdiff_t clen = 0;
14872
14873 for (int i = 0; i < f->n_tab_bar_items; i++)
14874 {
14875 Lisp_Object caption = AREF (f->tab_bar_items, (i * TAB_BAR_ITEM_NSLOTS
14876 + TAB_BAR_ITEM_CAPTION));
14877 if (NILP (caption))
14878 return Qnil;
14879 clen += SCHARS (caption);
14880 if (x < clen)
14881 {
14882 *prop_idx = i;
14883 *close_p = !NILP (Fget_text_property (make_fixnum (SCHARS (caption)
14884 - (clen - x)),
14885 Qclose_tab,
14886 caption));
14887 return caption;
14888 }
14889 }
14890 return Qnil;
14891 }
14892
14893
14894
14895
14896
14897
14898 Lisp_Object
14899 tty_handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
14900 struct input_event *event)
14901 {
14902
14903 if (y < FRAME_MENU_BAR_LINES (f)
14904 || y >= FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f))
14905 return Qnil;
14906
14907
14908 int prop_idx;
14909 bool close_p;
14910 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &close_p);
14911
14912 if (NILP (caption))
14913 return Qnil;
14914
14915 if (NILP (AREF (f->tab_bar_items,
14916 prop_idx * TAB_BAR_ITEM_NSLOTS + TAB_BAR_ITEM_ENABLED_P)))
14917 return Qnil;
14918
14919 if (down_p)
14920 f->last_tab_bar_item = prop_idx;
14921 else
14922 f->last_tab_bar_item = -1;
14923
14924 caption = Fcopy_sequence (caption);
14925
14926 AUTO_LIST2 (props, Qmenu_item,
14927 list3 (AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
14928 + TAB_BAR_ITEM_KEY),
14929 AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
14930 + TAB_BAR_ITEM_BINDING),
14931 close_p ? Qt : Qnil));
14932
14933 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14934 props, caption);
14935
14936 return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0)));
14937 }
14938
14939
14940
14941
14942
14943
14944
14945 #ifdef HAVE_WINDOW_SYSTEM
14946
14947
14948
14949
14950
14951
14952 static void
14953 update_tool_bar (struct frame *f, bool save_match_data)
14954 {
14955 #ifdef HAVE_EXT_TOOL_BAR
14956 bool do_update = FRAME_EXTERNAL_TOOL_BAR (f);
14957 #else
14958 bool do_update = (WINDOWP (f->tool_bar_window)
14959 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0);
14960 #endif
14961
14962 if (do_update)
14963 {
14964 Lisp_Object window;
14965 struct window *w;
14966
14967 window = FRAME_SELECTED_WINDOW (f);
14968 w = XWINDOW (window);
14969
14970
14971
14972
14973
14974
14975
14976
14977 if (windows_or_buffers_changed
14978 || w->update_mode_line
14979 || update_mode_lines
14980 || window_buffer_changed (w))
14981 {
14982 struct buffer *prev = current_buffer;
14983 specpdl_ref count = SPECPDL_INDEX ();
14984 Lisp_Object frame, new_tool_bar;
14985 int new_n_tool_bar;
14986
14987
14988
14989
14990 set_buffer_internal_1 (XBUFFER (w->contents));
14991
14992
14993 if (save_match_data)
14994 record_unwind_save_match_data ();
14995
14996
14997 if (NILP (Voverriding_local_map_menu_flag))
14998 {
14999 specbind (Qoverriding_terminal_local_map, Qnil);
15000 specbind (Qoverriding_local_map, Qnil);
15001 }
15002
15003
15004
15005
15006
15007 eassert (EQ (selected_window,
15008
15009
15010 XFRAME (selected_frame)->selected_window));
15011 record_unwind_protect (restore_selected_window, selected_window);
15012 XSETFRAME (frame, f);
15013 selected_frame = frame;
15014 selected_window = FRAME_SELECTED_WINDOW (f);
15015
15016
15017 new_tool_bar
15018 = tool_bar_items (Fcopy_sequence (f->tool_bar_items),
15019 &new_n_tool_bar);
15020
15021
15022 if (new_n_tool_bar != f->n_tool_bar_items
15023 || NILP (Fequal (new_tool_bar, f->tool_bar_items)))
15024 {
15025
15026
15027
15028 block_input ();
15029 fset_tool_bar_items (f, new_tool_bar);
15030 f->n_tool_bar_items = new_n_tool_bar;
15031 w->update_mode_line = true;
15032 unblock_input ();
15033 }
15034
15035 unbind_to (count, Qnil);
15036 set_buffer_internal_1 (prev);
15037 }
15038 }
15039 }
15040
15041 #ifndef HAVE_EXT_TOOL_BAR
15042
15043
15044
15045
15046
15047
15048
15049
15050 static void
15051 build_desired_tool_bar_string (struct frame *f)
15052 {
15053 int i, size, size_needed;
15054 Lisp_Object image, plist;
15055
15056 image = plist = Qnil;
15057
15058
15059
15060
15061
15062 size = (STRINGP (f->desired_tool_bar_string)
15063 ? SCHARS (f->desired_tool_bar_string)
15064 : 0);
15065
15066
15067 size_needed = f->n_tool_bar_items;
15068
15069
15070
15071 if (size < size_needed || NILP (f->desired_tool_bar_string))
15072
15073
15074 fset_desired_tool_bar_string (f, make_uninit_string (size_needed));
15075 else
15076 {
15077 AUTO_LIST4 (props, Qdisplay, Qnil, Qmenu_item, Qnil);
15078 Fremove_text_properties (make_fixnum (0), make_fixnum (size),
15079 props, f->desired_tool_bar_string);
15080 }
15081
15082 f->tool_bar_wraps_p = false;
15083
15084
15085
15086
15087 for (i = 0; i < f->n_tool_bar_items; ++i)
15088 {
15089 #define PROP(IDX) \
15090 AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
15091
15092 bool enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
15093 bool selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
15094 int hmargin, vmargin, relief, idx, end;
15095
15096 if (!NILP (PROP (TOOL_BAR_ITEM_WRAP)))
15097 {
15098
15099
15100 SSET (f->desired_tool_bar_string, i, '\n');
15101
15102
15103
15104 f->tool_bar_wraps_p = true;
15105 continue;
15106 }
15107
15108
15109 SSET (f->desired_tool_bar_string, i, ' ');
15110
15111
15112
15113 image = PROP (TOOL_BAR_ITEM_IMAGES);
15114 if (VECTORP (image))
15115 {
15116 if (enabled_p)
15117 idx = (selected_p
15118 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
15119 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
15120 else
15121 idx = (selected_p
15122 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
15123 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
15124
15125 eassert (ASIZE (image) >= idx);
15126 image = AREF (image, idx);
15127 }
15128 else
15129 idx = -1;
15130
15131
15132 if (!valid_image_p (image))
15133 continue;
15134
15135
15136 plist = Fcopy_sequence (XCDR (image));
15137
15138
15139 relief = (tool_bar_button_relief >= 0
15140 ? min (tool_bar_button_relief,
15141 min (INT_MAX, MOST_POSITIVE_FIXNUM))
15142 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
15143 hmargin = vmargin = relief;
15144
15145 if (RANGED_FIXNUMP (1, Vtool_bar_button_margin,
15146 INT_MAX - max (hmargin, vmargin)))
15147 {
15148 hmargin += XFIXNAT (Vtool_bar_button_margin);
15149 vmargin += XFIXNAT (Vtool_bar_button_margin);
15150 }
15151 else if (CONSP (Vtool_bar_button_margin))
15152 {
15153 if (RANGED_FIXNUMP (1, XCAR (Vtool_bar_button_margin),
15154 INT_MAX - hmargin))
15155 hmargin += XFIXNAT (XCAR (Vtool_bar_button_margin));
15156
15157 if (RANGED_FIXNUMP (1, XCDR (Vtool_bar_button_margin),
15158 INT_MAX - vmargin))
15159 vmargin += XFIXNAT (XCDR (Vtool_bar_button_margin));
15160 }
15161
15162 if (auto_raise_tool_bar_buttons_p)
15163 {
15164
15165
15166 if (selected_p)
15167 {
15168 plist = plist_put (plist, QCrelief, make_fixnum (-relief));
15169 hmargin -= relief;
15170 vmargin -= relief;
15171 }
15172 }
15173 else
15174 {
15175
15176
15177
15178 plist = plist_put (plist, QCrelief,
15179 (selected_p
15180 ? make_fixnum (-relief)
15181 : make_fixnum (relief)));
15182 hmargin -= relief;
15183 vmargin -= relief;
15184 }
15185
15186
15187 if (hmargin || vmargin)
15188 {
15189 if (hmargin == vmargin)
15190 plist = plist_put (plist, QCmargin, make_fixnum (hmargin));
15191 else
15192 plist = plist_put (plist, QCmargin,
15193 Fcons (make_fixnum (hmargin),
15194 make_fixnum (vmargin)));
15195 }
15196
15197
15198
15199
15200 if (!enabled_p && idx < 0)
15201 plist = plist_put (plist, QCconversion, Qdisabled);
15202
15203
15204
15205
15206
15207 image = Fcons (Qimage, plist);
15208 AUTO_LIST4 (props, Qdisplay, image, Qmenu_item,
15209 make_fixnum (i * TOOL_BAR_ITEM_NSLOTS));
15210
15211
15212
15213
15214 if (i + 1 == f->n_tool_bar_items)
15215 end = SCHARS (f->desired_tool_bar_string);
15216 else
15217 end = i + 1;
15218 Fadd_text_properties (make_fixnum (i), make_fixnum (end),
15219 props, f->desired_tool_bar_string);
15220 #undef PROP
15221 }
15222
15223
15224
15225
15226
15227
15228
15229 for (; i < size; ++i)
15230
15231 SSET (f->desired_tool_bar_string, i, ' ');
15232 }
15233
15234
15235
15236
15237
15238
15239
15240
15241
15242
15243
15244
15245
15246
15247
15248
15249
15250 static void
15251 display_tool_bar_line (struct it *it, int height)
15252 {
15253 struct glyph_row *row = it->glyph_row;
15254 int max_x = it->last_visible_x;
15255 struct glyph *last;
15256
15257
15258 clear_glyph_row (row);
15259 row->enabled_p = true;
15260 row->y = it->current_y;
15261
15262
15263
15264 it->start_of_box_run_p = true;
15265
15266 while (it->current_x < max_x)
15267 {
15268 int x, n_glyphs_before, i, nglyphs;
15269 struct it it_before;
15270
15271
15272 if (!get_next_display_element (it))
15273 {
15274
15275 if (height < 0 && !it->hpos)
15276 return;
15277 break;
15278 }
15279
15280
15281 n_glyphs_before = row->used[TEXT_AREA];
15282 it_before = *it;
15283
15284 PRODUCE_GLYPHS (it);
15285
15286 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
15287 i = 0;
15288 x = it_before.current_x;
15289 while (i < nglyphs)
15290 {
15291 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
15292
15293 if (x + glyph->pixel_width > max_x)
15294 {
15295
15296 row->used[TEXT_AREA] = n_glyphs_before;
15297 *it = it_before;
15298
15299
15300
15301 if (n_glyphs_before == 0
15302 && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
15303 break;
15304 goto out;
15305 }
15306
15307 ++it->hpos;
15308 x += glyph->pixel_width;
15309 ++i;
15310 }
15311
15312
15313
15314
15315
15316
15317 if (ITERATOR_AT_END_OF_LINE_P (it))
15318 {
15319 reseat_at_next_visible_line_start (it, false);
15320 break;
15321 }
15322
15323 if (ITERATOR_AT_END_P (it))
15324 break;
15325
15326 set_iterator_to_next (it, true);
15327 }
15328
15329 out:;
15330
15331 row->displays_text_p = row->used[TEXT_AREA] != 0;
15332
15333
15334
15335
15336
15337
15338
15339 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
15340 && !EQ (Vauto_resize_tool_bars, Qgrow_only))
15341 it->face_id = DEFAULT_FACE_ID;
15342
15343 extend_face_to_end_of_line (it);
15344 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
15345 last->right_box_line_p = true;
15346 if (last == row->glyphs[TEXT_AREA])
15347 last->left_box_line_p = true;
15348
15349
15350 if (height != -1
15351 && (height -= it->max_ascent + it->max_descent) > 0)
15352 {
15353
15354 height %= FRAME_LINE_HEIGHT (it->f);
15355 it->max_ascent += height / 2;
15356 it->max_descent += (height + 1) / 2;
15357 }
15358
15359 compute_line_metrics (it);
15360
15361
15362 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row))
15363 {
15364 row->height = row->phys_height = it->last_visible_y - row->y;
15365 row->visible_height = row->height;
15366 row->ascent = row->phys_ascent = 0;
15367 row->extra_line_spacing = 0;
15368 }
15369
15370 row->full_width_p = true;
15371 row->continued_p = false;
15372 row->truncated_on_left_p = false;
15373 row->truncated_on_right_p = false;
15374
15375 it->current_x = it->hpos = 0;
15376 it->current_y += row->height;
15377 ++it->vpos;
15378 ++it->glyph_row;
15379 }
15380
15381
15382
15383
15384
15385
15386 static int
15387 tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
15388 {
15389 struct window *w = XWINDOW (f->tool_bar_window);
15390 struct it it;
15391
15392
15393
15394 struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
15395
15396
15397
15398 init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID);
15399 temp_row->reversed_p = false;
15400 it.first_visible_x = 0;
15401 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
15402 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
15403 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
15404 it.paragraph_embedding = L2R;
15405
15406 while (!ITERATOR_AT_END_P (&it))
15407 {
15408 clear_glyph_row (temp_row);
15409 it.glyph_row = temp_row;
15410 display_tool_bar_line (&it, -1);
15411 }
15412 clear_glyph_row (temp_row);
15413
15414
15415 if (n_rows)
15416 *n_rows = it.vpos > 0 ? it.vpos : -1;
15417
15418 if (pixelwise)
15419 return it.current_y;
15420 else
15421 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
15422 }
15423
15424 #endif
15425
15426 DEFUN ("tool-bar-height", Ftool_bar_height, Stool_bar_height,
15427 0, 2, 0,
15428 doc:
15429
15430 )
15431 (Lisp_Object frame, Lisp_Object pixelwise)
15432 {
15433 int height = 0;
15434
15435 #ifndef HAVE_EXT_TOOL_BAR
15436 struct frame *f = decode_any_frame (frame);
15437
15438 if (WINDOWP (f->tool_bar_window)
15439 && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tool_bar_window)) > 0)
15440 {
15441 update_tool_bar (f, true);
15442 if (f->n_tool_bar_items)
15443 {
15444 build_desired_tool_bar_string (f);
15445 height = tool_bar_height (f, NULL, !NILP (pixelwise));
15446 }
15447 }
15448 #endif
15449
15450 return make_fixnum (height);
15451 }
15452
15453 #ifndef HAVE_EXT_TOOL_BAR
15454
15455
15456
15457 static bool
15458 redisplay_tool_bar (struct frame *f)
15459 {
15460 struct window *w;
15461 struct it it;
15462 struct glyph_row *row;
15463 bool change_height_p;
15464
15465 change_height_p = false;
15466 f->tool_bar_redisplayed = true;
15467
15468
15469
15470
15471
15472 if (!WINDOWP (f->tool_bar_window)
15473 || (w = XWINDOW (f->tool_bar_window),
15474 WINDOW_TOTAL_LINES (w) == 0))
15475 {
15476
15477
15478
15479
15480
15481 f->tool_bar_resized = true;
15482
15483 return false;
15484 }
15485
15486
15487 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
15488 it.first_visible_x = 0;
15489 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
15490 row = it.glyph_row;
15491 row->reversed_p = false;
15492
15493
15494 build_desired_tool_bar_string (f);
15495 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
15496 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
15497
15498
15499
15500
15501
15502
15503
15504 it.paragraph_embedding = L2R;
15505
15506 if (f->n_tool_bar_rows == 0)
15507 {
15508 int new_height = tool_bar_height (f, &f->n_tool_bar_rows, true);
15509
15510 if (new_height != WINDOW_PIXEL_HEIGHT (w))
15511 {
15512 if (FRAME_TERMINAL (f)->change_tool_bar_height_hook)
15513 FRAME_TERMINAL (f)->change_tool_bar_height_hook (f, new_height);
15514 frame_default_tool_bar_height = new_height;
15515
15516 clear_glyph_matrix (w->desired_matrix);
15517 f->fonts_changed = true;
15518
15519
15520
15521
15522
15523
15524
15525 resize_frame_windows (f, FRAME_INNER_HEIGHT (f), false);
15526
15527 return true;
15528 }
15529 }
15530
15531
15532
15533 if (f->n_tool_bar_rows > 0)
15534 {
15535 int border, rows, height, extra;
15536
15537 if (TYPE_RANGED_FIXNUMP (int, Vtool_bar_border))
15538 border = XFIXNUM (Vtool_bar_border);
15539 else if (EQ (Vtool_bar_border, Qinternal_border_width))
15540 border = FRAME_INTERNAL_BORDER_WIDTH (f);
15541 else if (EQ (Vtool_bar_border, Qborder_width))
15542 border = f->border_width;
15543 else
15544 border = 0;
15545 if (border < 0)
15546 border = 0;
15547
15548 rows = f->n_tool_bar_rows;
15549
15550 if (f->tool_bar_wraps_p)
15551 {
15552
15553
15554
15555 while (!ITERATOR_AT_END_P (&it))
15556 display_tool_bar_line (&it, -1);
15557
15558
15559
15560
15561
15562
15563 if (it.current_y != it.last_visible_y)
15564 change_height_p = true;
15565 }
15566 else
15567 {
15568 height = max (1, (it.last_visible_y - border) / rows);
15569 extra = it.last_visible_y - border - height * rows;
15570
15571 while (it.current_y < it.last_visible_y)
15572 {
15573 int h = 0;
15574 if (extra > 0 && rows-- > 0)
15575 {
15576 h = (extra + rows - 1) / rows;
15577 extra -= h;
15578 }
15579
15580 display_tool_bar_line (&it, height + h);
15581 }
15582 }
15583 }
15584 else
15585 {
15586 while (it.current_y < it.last_visible_y)
15587 display_tool_bar_line (&it, 0);
15588 }
15589
15590
15591
15592 w->desired_matrix->no_scrolling_p = true;
15593 w->must_be_updated_p = true;
15594
15595 if (!NILP (Vauto_resize_tool_bars))
15596 {
15597
15598
15599 if (IT_STRING_CHARPOS (it) < it.end_charpos)
15600 change_height_p = true;
15601
15602
15603
15604
15605
15606 row = it.glyph_row - 1;
15607
15608
15609
15610
15611 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
15612 && row->height >= FRAME_LINE_HEIGHT (f))
15613 change_height_p = true;
15614
15615
15616
15617 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
15618 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
15619 change_height_p = true;
15620
15621
15622
15623 if (change_height_p)
15624 {
15625 int nrows;
15626 int new_height = tool_bar_height (f, &nrows, true);
15627
15628 change_height_p = ((EQ (Vauto_resize_tool_bars, Qgrow_only)
15629 && !f->minimize_tool_bar_window_p)
15630 ? (new_height > WINDOW_PIXEL_HEIGHT (w))
15631 : (new_height != WINDOW_PIXEL_HEIGHT (w)));
15632 f->minimize_tool_bar_window_p = false;
15633
15634 if (change_height_p)
15635 {
15636 if (FRAME_TERMINAL (f)->change_tool_bar_height_hook)
15637 FRAME_TERMINAL (f)->change_tool_bar_height_hook (f, new_height);
15638 frame_default_tool_bar_height = new_height;
15639 clear_glyph_matrix (w->desired_matrix);
15640 f->n_tool_bar_rows = nrows;
15641 f->fonts_changed = true;
15642
15643 return true;
15644 }
15645 }
15646 }
15647
15648 f->minimize_tool_bar_window_p = false;
15649
15650 return false;
15651 }
15652
15653
15654
15655
15656
15657
15658 static bool
15659 tool_bar_item_info (struct frame *f, struct glyph *glyph, int *prop_idx)
15660 {
15661 Lisp_Object prop;
15662 ptrdiff_t charpos;
15663
15664
15665
15666
15667 charpos = min (SCHARS (f->current_tool_bar_string), glyph->charpos);
15668 charpos = max (0, charpos);
15669
15670
15671
15672
15673 prop = Fget_text_property (make_fixnum (charpos),
15674 Qmenu_item, f->current_tool_bar_string);
15675 if (! FIXNUMP (prop))
15676 return false;
15677 *prop_idx = XFIXNUM (prop);
15678 return true;
15679 }
15680
15681
15682
15683
15684
15685
15686
15687
15688
15689
15690
15691
15692 static int
15693 get_tool_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
15694 int *hpos, int *vpos, int *prop_idx)
15695 {
15696 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15697 struct window *w = XWINDOW (f->tool_bar_window);
15698 int area;
15699
15700
15701 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
15702 if (*glyph == NULL)
15703 return -1;
15704
15705
15706
15707 if (!tool_bar_item_info (f, *glyph, prop_idx))
15708 return -1;
15709
15710
15711 if (EQ (f->tool_bar_window, hlinfo->mouse_face_window)
15712 && *vpos >= hlinfo->mouse_face_beg_row
15713 && *vpos <= hlinfo->mouse_face_end_row
15714 && (*vpos > hlinfo->mouse_face_beg_row
15715 || *hpos >= hlinfo->mouse_face_beg_col)
15716 && (*vpos < hlinfo->mouse_face_end_row
15717 || *hpos < hlinfo->mouse_face_end_col
15718 || hlinfo->mouse_face_past_end))
15719 return 0;
15720
15721 return 1;
15722 }
15723
15724
15725
15726
15727
15728
15729
15730
15731 void
15732 handle_tool_bar_click_with_device (struct frame *f, int x, int y, bool down_p,
15733 int modifiers, Lisp_Object device)
15734 {
15735 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15736 struct window *w = XWINDOW (f->tool_bar_window);
15737 int hpos, vpos, prop_idx;
15738 struct glyph *glyph;
15739 Lisp_Object enabled_p;
15740 int ts;
15741
15742
15743
15744
15745
15746
15747
15748
15749 frame_to_window_pixel_xy (w, &x, &y);
15750 ts = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
15751 if (ts == -1
15752 || (ts != 0 && !NILP (Vmouse_highlight)))
15753 return;
15754
15755
15756
15757
15758 if (NILP (Vmouse_highlight) && !down_p)
15759 prop_idx = f->last_tool_bar_item;
15760
15761
15762 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
15763 if (NILP (enabled_p))
15764 return;
15765
15766 if (down_p)
15767 {
15768
15769 if (!NILP (Vmouse_highlight))
15770 show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
15771 f->last_tool_bar_item = prop_idx;
15772 }
15773 else
15774 {
15775 Lisp_Object key, frame;
15776 struct input_event event;
15777 EVENT_INIT (event);
15778
15779
15780 if (!NILP (Vmouse_highlight))
15781 show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
15782
15783 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
15784
15785 XSETFRAME (frame, f);
15786 event.kind = TOOL_BAR_EVENT;
15787 event.frame_or_window = frame;
15788 event.arg = key;
15789 event.modifiers = modifiers;
15790 event.device = device;
15791 kbd_buffer_store_event (&event);
15792 f->last_tool_bar_item = -1;
15793 }
15794 }
15795
15796 void
15797 handle_tool_bar_click (struct frame *f, int x, int y, bool down_p,
15798 int modifiers)
15799 {
15800 handle_tool_bar_click_with_device (f, x, y, down_p, modifiers, Qt);
15801 }
15802
15803
15804
15805
15806
15807 static void
15808 note_tool_bar_highlight (struct frame *f, int x, int y)
15809 {
15810 Lisp_Object window = f->tool_bar_window;
15811 struct window *w = XWINDOW (window);
15812 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
15813 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15814 int hpos, vpos;
15815 struct glyph *glyph;
15816 struct glyph_row *row;
15817 int i;
15818 Lisp_Object enabled_p;
15819 int prop_idx;
15820 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
15821 bool mouse_down_p;
15822 int rc;
15823
15824
15825
15826 if (x <= 0 || y <= 0)
15827 {
15828 clear_mouse_face (hlinfo);
15829 return;
15830 }
15831
15832 rc = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
15833 if (rc < 0)
15834 {
15835
15836 clear_mouse_face (hlinfo);
15837 return;
15838 }
15839 else if (rc == 0)
15840
15841 goto set_help_echo;
15842
15843 clear_mouse_face (hlinfo);
15844
15845
15846 mouse_down_p = (gui_mouse_grabbed (dpyinfo)
15847 && f == dpyinfo->last_mouse_frame);
15848
15849 if (mouse_down_p && f->last_tool_bar_item != prop_idx)
15850 return;
15851
15852 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
15853
15854
15855 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
15856 if (!NILP (enabled_p) && !NILP (Vmouse_highlight))
15857 {
15858
15859
15860 row = MATRIX_ROW (w->current_matrix, vpos);
15861 for (i = x = 0; i < hpos; ++i)
15862 x += row->glyphs[TEXT_AREA][i].pixel_width;
15863
15864
15865 hlinfo->mouse_face_beg_col = hpos;
15866 hlinfo->mouse_face_beg_row = vpos;
15867 hlinfo->mouse_face_beg_x = x;
15868 hlinfo->mouse_face_past_end = false;
15869
15870 hlinfo->mouse_face_end_col = hpos + 1;
15871 hlinfo->mouse_face_end_row = vpos;
15872 hlinfo->mouse_face_end_x = x + glyph->pixel_width;
15873 hlinfo->mouse_face_window = window;
15874 hlinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
15875
15876
15877 show_mouse_face (hlinfo, draw);
15878 }
15879
15880 set_help_echo:
15881
15882
15883
15884 help_echo_object = help_echo_window = Qnil;
15885 help_echo_pos = -1;
15886 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
15887 if (NILP (help_echo_string))
15888 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
15889 }
15890
15891 #endif
15892
15893 #endif
15894
15895
15896
15897
15898
15899
15900
15901
15902
15903
15904
15905
15906
15907 static bool
15908 hscroll_window_tree (Lisp_Object window)
15909 {
15910 bool hscrolled_p = false;
15911 bool hscroll_relative_p = FLOATP (Vhscroll_step);
15912 int hscroll_step_abs = 0;
15913 double hscroll_step_rel = 0;
15914
15915 if (hscroll_relative_p)
15916 {
15917 hscroll_step_rel = XFLOAT_DATA (Vhscroll_step);
15918 if (hscroll_step_rel < 0)
15919 {
15920 hscroll_relative_p = false;
15921 hscroll_step_abs = 0;
15922 }
15923 }
15924 else if (TYPE_RANGED_FIXNUMP (int, Vhscroll_step))
15925 {
15926 hscroll_step_abs = XFIXNUM (Vhscroll_step);
15927 if (hscroll_step_abs < 0)
15928 hscroll_step_abs = 0;
15929 }
15930 else
15931 hscroll_step_abs = 0;
15932
15933 while (WINDOWP (window))
15934 {
15935 struct window *w = XWINDOW (window);
15936
15937 if (WINDOWP (w->contents))
15938 hscrolled_p |= hscroll_window_tree (w->contents);
15939 else if (w->cursor.vpos >= 0
15940
15941
15942
15943
15944
15945
15946 && !(w == XWINDOW (echo_area_window)
15947 && !NILP (echo_area_buffer[0])))
15948 {
15949 int h_margin;
15950 int text_area_width;
15951 struct glyph_row *cursor_row;
15952 struct glyph_row *bottom_row;
15953
15954 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->desired_matrix, w);
15955 if (w->cursor.vpos < bottom_row - w->desired_matrix->rows)
15956 cursor_row = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
15957 else
15958 cursor_row = bottom_row - 1;
15959
15960 if (!cursor_row->enabled_p)
15961 {
15962 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
15963 if (w->cursor.vpos < bottom_row - w->current_matrix->rows)
15964 cursor_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
15965 else
15966 cursor_row = bottom_row - 1;
15967 }
15968 bool row_r2l_p = cursor_row->reversed_p;
15969 bool hscl = hscrolling_current_line_p (w);
15970 int x_offset = 0;
15971
15972
15973 if (!NILP (Vdisplay_line_numbers))
15974 {
15975 struct glyph *g;
15976 if (!row_r2l_p)
15977 {
15978 for (g = cursor_row->glyphs[TEXT_AREA];
15979 g < cursor_row->glyphs[TEXT_AREA]
15980 + cursor_row->used[TEXT_AREA];
15981 g++)
15982 {
15983 if (!(NILP (g->object) && g->charpos < 0))
15984 break;
15985 x_offset += g->pixel_width;
15986 }
15987 }
15988 else
15989 {
15990 for (g = cursor_row->glyphs[TEXT_AREA]
15991 + cursor_row->used[TEXT_AREA];
15992 g > cursor_row->glyphs[TEXT_AREA];
15993 g--)
15994 {
15995 if (!(NILP ((g - 1)->object) && (g - 1)->charpos < 0))
15996 break;
15997 x_offset += (g - 1)->pixel_width;
15998 }
15999 }
16000 }
16001 if (cursor_row->truncated_on_left_p)
16002 {
16003
16004 struct frame *f = XFRAME (WINDOW_FRAME (w));
16005 x_offset -= (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
16006 }
16007
16008 text_area_width = window_box_width (w, TEXT_AREA);
16009
16010
16011 h_margin = (clip_to_bounds (0, hscroll_margin, 1000000)
16012 * WINDOW_FRAME_COLUMN_WIDTH (w));
16013
16014
16015
16016 if (w->suspend_auto_hscroll
16017 && NILP (Fequal (Fwindow_point (window),
16018 Fwindow_old_point (window))))
16019 {
16020 w->suspend_auto_hscroll = false;
16021
16022
16023
16024
16025 if (w->min_hscroll == 0 && w->hscroll > 0
16026 && EQ (Fbuffer_local_value (Qauto_hscroll_mode, w->contents),
16027 Qcurrent_line))
16028 SET_FRAME_GARBAGED (XFRAME (w->frame));
16029 }
16030
16031
16032 Fset_marker (w->old_pointm,
16033 ((w == XWINDOW (selected_window))
16034 ? make_fixnum (BUF_PT (XBUFFER (w->contents)))
16035 : Fmarker_position (w->pointm)),
16036 w->contents);
16037
16038 if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->contents))
16039 && !w->suspend_auto_hscroll
16040
16041
16042
16043
16044
16045
16046 && (CHARPOS (cursor_row->start.pos)
16047 >= BUF_BEG (XBUFFER (w->contents)))
16048
16049
16050
16051
16052 && ((!row_r2l_p
16053 && ((w->hscroll && w->cursor.x <= h_margin + x_offset)
16054 || (cursor_row->enabled_p
16055 && cursor_row->truncated_on_right_p
16056 && (w->cursor.x >= text_area_width - h_margin))))
16057
16058
16059
16060
16061
16062
16063 || (row_r2l_p
16064 && ((cursor_row->enabled_p
16065
16066
16067
16068 && cursor_row->truncated_on_right_p
16069 && w->cursor.x <= h_margin)
16070 || (w->hscroll
16071 && (w->cursor.x >= (text_area_width - h_margin
16072 - x_offset)))))
16073
16074
16075
16076
16077
16078 || (hscl
16079 && w->hscroll != w->min_hscroll
16080 && !cursor_row->truncated_on_left_p)))
16081 {
16082 struct it it;
16083 ptrdiff_t hscroll;
16084 struct buffer *saved_current_buffer;
16085 ptrdiff_t pt;
16086 int wanted_x;
16087
16088
16089 saved_current_buffer = current_buffer;
16090 current_buffer = XBUFFER (w->contents);
16091
16092 if (w == XWINDOW (selected_window))
16093 pt = PT;
16094 else
16095 pt = clip_to_bounds (BEGV, marker_position (w->pointm), ZV);
16096
16097
16098
16099 init_to_row_start (&it, w, cursor_row);
16100 if (hscl)
16101 it.first_visible_x = window_hscroll_limited (w, it.f)
16102 * FRAME_COLUMN_WIDTH (it.f);
16103 it.last_visible_x = DISP_INFINITY;
16104
16105 ptrdiff_t nchars = pt - IT_CHARPOS (it);
16106 if (current_buffer->long_line_optimizations_p
16107 && nchars > large_hscroll_threshold)
16108 {
16109
16110
16111
16112
16113 fast_move_it_horizontally (&it, nchars);
16114 it.current_x += nchars * FRAME_COLUMN_WIDTH (it.f);
16115 }
16116 else
16117 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
16118
16119
16120
16121
16122
16123
16124 if (it.method == GET_FROM_STRING && pt > 1)
16125 {
16126 init_to_row_start (&it, w, cursor_row);
16127 if (hscl)
16128 it.first_visible_x = (window_hscroll_limited (w, it.f)
16129 * FRAME_COLUMN_WIDTH (it.f));
16130 if (current_buffer->long_line_optimizations_p
16131 && nchars > large_hscroll_threshold)
16132 {
16133 fast_move_it_horizontally (&it, nchars - 1);
16134 it.current_x += (nchars - 1) * FRAME_COLUMN_WIDTH (it.f);
16135 }
16136 else
16137 move_it_in_display_line_to (&it, pt - 1, -1, MOVE_TO_POS);
16138 }
16139 current_buffer = saved_current_buffer;
16140
16141
16142 if (!hscroll_relative_p && hscroll_step_abs == 0)
16143 hscroll = max (0, (it.current_x
16144 - (ITERATOR_AT_END_OF_LINE_P (&it)
16145 ? (text_area_width - 4 * FRAME_COLUMN_WIDTH (it.f))
16146 : (text_area_width / 2))))
16147 / FRAME_COLUMN_WIDTH (it.f);
16148 else if ((!row_r2l_p
16149 && w->cursor.x >= text_area_width - h_margin)
16150 || (row_r2l_p && w->cursor.x <= h_margin))
16151 {
16152 if (hscroll_relative_p)
16153 wanted_x = text_area_width * (1 - hscroll_step_rel)
16154 - h_margin;
16155 else
16156 wanted_x = text_area_width
16157 - hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
16158 - h_margin;
16159 hscroll
16160 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
16161 }
16162 else
16163 {
16164 if (hscroll_relative_p)
16165 wanted_x =
16166 text_area_width * hscroll_step_rel + h_margin + x_offset;
16167 else
16168 wanted_x =
16169 hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
16170 + h_margin + x_offset;
16171 hscroll
16172 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
16173 }
16174 hscroll = max (hscroll, w->min_hscroll);
16175
16176
16177
16178
16179 if (w->hscroll != hscroll
16180
16181
16182
16183
16184 || (hscl && w->last_cursor_vpos != w->cursor.vpos))
16185 {
16186 struct buffer *b = XBUFFER (w->contents);
16187 b->prevent_redisplay_optimizations_p = true;
16188 w->hscroll = hscroll;
16189 hscrolled_p = true;
16190 }
16191 }
16192 }
16193
16194 window = w->next;
16195 }
16196
16197
16198 return hscrolled_p;
16199 }
16200
16201
16202
16203
16204
16205
16206
16207
16208 static bool
16209 hscroll_windows (Lisp_Object window)
16210 {
16211 bool hscrolled_p = hscroll_window_tree (window);
16212 if (hscrolled_p)
16213 clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
16214 return hscrolled_p;
16215 }
16216
16217
16218
16219
16220
16221
16222
16223
16224
16225
16226 #ifdef GLYPH_DEBUG
16227
16228
16229
16230 static int debug_first_unchanged_at_end_vpos;
16231 static int debug_last_unchanged_at_beg_vpos;
16232
16233
16234
16235 static int debug_dvpos, debug_dy;
16236
16237
16238
16239 static ptrdiff_t debug_delta, debug_delta_bytes;
16240
16241
16242
16243
16244 static ptrdiff_t debug_end_vpos;
16245
16246
16247
16248
16249
16250 static void debug_method_add (struct window *, char const *, ...)
16251 ATTRIBUTE_FORMAT_PRINTF (2, 3);
16252
16253 static void
16254 debug_method_add (struct window *w, char const *fmt, ...)
16255 {
16256 void *ptr = w;
16257 char *method = w->desired_matrix->method;
16258 int len = strlen (method);
16259 int size = sizeof w->desired_matrix->method;
16260 int remaining = size - len - 1;
16261 va_list ap;
16262
16263 if (len && remaining)
16264 {
16265 method[len] = '|';
16266 --remaining, ++len;
16267 }
16268
16269 va_start (ap, fmt);
16270 vsnprintf (method + len, remaining + 1, fmt, ap);
16271 va_end (ap);
16272
16273 if (trace_redisplay_p)
16274 fprintf (stderr, "%p (%s): %s\n",
16275 ptr,
16276 ((BUFFERP (w->contents)
16277 && STRINGP (BVAR (XBUFFER (w->contents), name)))
16278 ? SSDATA (BVAR (XBUFFER (w->contents), name))
16279 : "no buffer"),
16280 method + len);
16281 }
16282
16283 #endif
16284
16285
16286
16287
16288
16289
16290
16291 static bool
16292 text_outside_line_unchanged_p (struct window *w,
16293 ptrdiff_t start, ptrdiff_t end)
16294 {
16295 bool unchanged_p = true;
16296
16297
16298 if (window_outdated (w))
16299 {
16300
16301 if (GPT < start || Z - GPT < end)
16302 unchanged_p = false;
16303
16304
16305 if (unchanged_p
16306 && (BEG_UNCHANGED < start - 1
16307 || END_UNCHANGED < end))
16308 unchanged_p = false;
16309
16310
16311
16312 if (unchanged_p
16313 && FIXNUMP (BVAR (current_buffer, selective_display))
16314 && XFIXNUM (BVAR (current_buffer, selective_display)) > 0
16315 && (BEG_UNCHANGED < start || GPT <= start))
16316 unchanged_p = false;
16317
16318
16319
16320
16321
16322
16323
16324
16325 if (unchanged_p)
16326 {
16327 if (BEG + BEG_UNCHANGED == start
16328 && overlay_touches_p (start))
16329 unchanged_p = false;
16330 if (END_UNCHANGED == end
16331 && overlay_touches_p (Z - end))
16332 unchanged_p = false;
16333 }
16334
16335
16336
16337
16338
16339
16340
16341
16342 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
16343 && NILP (BVAR (XBUFFER (w->contents), bidi_paragraph_direction)))
16344 unchanged_p = false;
16345 }
16346
16347 return unchanged_p;
16348 }
16349
16350
16351
16352
16353
16354
16355
16356
16357
16358 void
16359 redisplay (void)
16360 {
16361 redisplay_internal ();
16362 }
16363
16364
16365 static Lisp_Object
16366 overlay_arrow_string_or_property (Lisp_Object var)
16367 {
16368 Lisp_Object val;
16369
16370 if (val = Fget (var, Qoverlay_arrow_string), STRINGP (val))
16371 return val;
16372
16373 return Voverlay_arrow_string;
16374 }
16375
16376
16377 static bool
16378 overlay_arrow_in_current_buffer_p (void)
16379 {
16380 Lisp_Object vlist;
16381
16382 for (vlist = Voverlay_arrow_variable_list;
16383 CONSP (vlist);
16384 vlist = XCDR (vlist))
16385 {
16386 Lisp_Object var = XCAR (vlist);
16387 Lisp_Object val;
16388
16389 if (!SYMBOLP (var))
16390 continue;
16391 val = find_symbol_value (var);
16392 if (MARKERP (val)
16393 && current_buffer == XMARKER (val)->buffer)
16394 return true;
16395 }
16396 return false;
16397 }
16398
16399
16400
16401
16402
16403
16404
16405 static bool
16406 overlay_arrows_changed_p (bool set_redisplay)
16407 {
16408 Lisp_Object vlist;
16409 bool changed = false;
16410
16411 for (vlist = Voverlay_arrow_variable_list;
16412 CONSP (vlist);
16413 vlist = XCDR (vlist))
16414 {
16415 Lisp_Object var = XCAR (vlist);
16416 Lisp_Object val, pstr;
16417
16418 if (!SYMBOLP (var))
16419 continue;
16420 val = find_symbol_value (var);
16421 if (!MARKERP (val))
16422 continue;
16423 if (! EQ (Fmarker_position (val),
16424
16425
16426 Fget (var, Qlast_arrow_position))
16427 || ! (pstr = overlay_arrow_string_or_property (var),
16428 EQ (pstr, Fget (var, Qlast_arrow_string))))
16429 {
16430 struct buffer *buf = XMARKER (val)->buffer;
16431
16432 if (set_redisplay)
16433 {
16434 if (buf)
16435 bset_redisplay (buf);
16436 changed = true;
16437 }
16438 else
16439 return true;
16440 }
16441 }
16442 return changed;
16443 }
16444
16445
16446
16447 static void
16448 update_overlay_arrows (int up_to_date)
16449 {
16450 Lisp_Object vlist;
16451
16452 for (vlist = Voverlay_arrow_variable_list;
16453 CONSP (vlist);
16454 vlist = XCDR (vlist))
16455 {
16456 Lisp_Object var = XCAR (vlist);
16457
16458 if (!SYMBOLP (var))
16459 continue;
16460
16461 if (up_to_date > 0)
16462 {
16463 Lisp_Object val = find_symbol_value (var);
16464 if (!MARKERP (val))
16465 continue;
16466 Fput (var, Qlast_arrow_position, Fmarker_position (val));
16467 Fput (var, Qlast_arrow_string,
16468 overlay_arrow_string_or_property (var));
16469 }
16470 else if (up_to_date < 0
16471 || !NILP (Fget (var, Qlast_arrow_position)))
16472 {
16473 Fput (var, Qlast_arrow_position, Qt);
16474 Fput (var, Qlast_arrow_string, Qt);
16475 }
16476 }
16477 }
16478
16479
16480
16481
16482
16483
16484 static Lisp_Object
16485 overlay_arrow_at_row (struct it *it, struct glyph_row *row)
16486 {
16487 Lisp_Object vlist;
16488
16489 for (vlist = Voverlay_arrow_variable_list;
16490 CONSP (vlist);
16491 vlist = XCDR (vlist))
16492 {
16493 Lisp_Object var = XCAR (vlist);
16494 Lisp_Object val;
16495
16496 if (!SYMBOLP (var))
16497 continue;
16498
16499 val = find_symbol_value (var);
16500
16501 if (MARKERP (val)
16502 && current_buffer == XMARKER (val)->buffer
16503 && (MATRIX_ROW_START_CHARPOS (row) == marker_position (val)))
16504 {
16505 if (FRAME_WINDOW_P (it->f)
16506
16507
16508 && WINDOW_LEFT_FRINGE_WIDTH (it->w) > 0)
16509 {
16510 #ifdef HAVE_WINDOW_SYSTEM
16511 if (val = Fget (var, Qoverlay_arrow_bitmap), SYMBOLP (val))
16512 {
16513 int fringe_bitmap = lookup_fringe_bitmap (val);
16514 if (fringe_bitmap != 0)
16515 return make_fixnum (fringe_bitmap);
16516 }
16517 #endif
16518 return make_fixnum (-1);
16519 }
16520 return overlay_arrow_string_or_property (var);
16521 }
16522 }
16523
16524 return Qnil;
16525 }
16526
16527
16528
16529
16530
16531 static bool
16532 check_point_in_composition (struct buffer *prev_buf, ptrdiff_t prev_pt,
16533 struct buffer *buf, ptrdiff_t pt)
16534 {
16535 ptrdiff_t start, end;
16536 Lisp_Object prop;
16537 Lisp_Object buffer;
16538
16539 XSETBUFFER (buffer, buf);
16540
16541
16542 if (prev_buf == buf)
16543 {
16544 if (prev_pt == pt)
16545
16546 return false;
16547
16548 if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
16549 && find_composition (prev_pt, -1, &start, &end, &prop, buffer)
16550 && composition_valid_p (start, end, prop)
16551 && start < prev_pt && end > prev_pt)
16552
16553
16554 return (pt <= start || pt >= end);
16555 }
16556
16557
16558 return (pt > BUF_BEGV (buf) && pt < BUF_ZV (buf)
16559 && find_composition (pt, -1, &start, &end, &prop, buffer)
16560 && composition_valid_p (start, end, prop)
16561 && start < pt && end > pt);
16562 }
16563
16564
16565
16566 static void
16567 reconsider_clip_changes (struct window *w)
16568 {
16569 struct buffer *b = XBUFFER (w->contents);
16570
16571 if (b->clip_changed
16572 && w->window_end_valid
16573 && w->current_matrix->buffer == b
16574 && w->current_matrix->zv == BUF_ZV (b)
16575 && w->current_matrix->begv == BUF_BEGV (b))
16576 b->clip_changed = false;
16577
16578
16579
16580
16581
16582 if (!b->clip_changed && w->window_end_valid)
16583 {
16584 ptrdiff_t pt = (w == XWINDOW (selected_window)
16585 ? PT : marker_position (w->pointm));
16586
16587 if ((w->current_matrix->buffer != b || pt != w->last_point)
16588 && check_point_in_composition (w->current_matrix->buffer,
16589 w->last_point, b, pt))
16590 b->clip_changed = true;
16591 }
16592 }
16593
16594 static void
16595 propagate_buffer_redisplay (void)
16596 {
16597
16598
16599
16600
16601
16602
16603
16604
16605
16606 Lisp_Object ws = window_list ();
16607 for (; CONSP (ws); ws = XCDR (ws))
16608 {
16609 struct window *thisw = XWINDOW (XCAR (ws));
16610 struct buffer *thisb = XBUFFER (thisw->contents);
16611 if (thisb->text->redisplay)
16612 thisw->redisplay = true;
16613 }
16614 }
16615
16616 #define STOP_POLLING \
16617 do { if (! polling_stopped_here) stop_polling (); \
16618 polling_stopped_here = true; } while (false)
16619
16620 #define RESUME_POLLING \
16621 do { if (polling_stopped_here) start_polling (); \
16622 polling_stopped_here = false; } while (false)
16623
16624
16625
16626
16627 static void
16628 redisplay_internal (void)
16629 {
16630 struct window *w = XWINDOW (selected_window);
16631 struct window *sw;
16632 struct frame *fr;
16633 bool pending;
16634 bool must_finish = false, match_p;
16635 struct text_pos tlbufpos, tlendpos;
16636 int number_of_visible_frames;
16637 struct frame *sf;
16638 bool polling_stopped_here = false;
16639 Lisp_Object tail, frame;
16640
16641
16642
16643
16644 enum { MAX_HSCROLL_RETRIES = 16 };
16645 int hscroll_retries = 0;
16646
16647
16648
16649
16650
16651
16652 enum {MAX_GARBAGED_FRAME_RETRIES = 2 };
16653 int garbaged_frame_retries = 0;
16654
16655
16656
16657
16658 bool consider_all_windows_p;
16659
16660
16661 bool update_miniwindow_p = false;
16662
16663 redisplay_trace ("redisplay_internal %d\n", redisplaying_p);
16664
16665
16666
16667
16668 if ((FRAME_INITIAL_P (SELECTED_FRAME ())
16669 && redisplay_skip_initial_frame)
16670 || !NILP (Vinhibit_redisplay))
16671 return;
16672
16673
16674
16675
16676 fr = XFRAME (w->frame);
16677 sf = SELECTED_FRAME ();
16678
16679 if (!fr->glyphs_initialized_p)
16680 return;
16681
16682 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS)
16683 if (popup_activated ())
16684 return;
16685 #endif
16686
16687 #if defined (HAVE_HAIKU)
16688 if (popup_activated_p)
16689 return;
16690 #endif
16691
16692
16693 if (redisplaying_p)
16694 return;
16695
16696
16697
16698 specpdl_ref count = SPECPDL_INDEX ();
16699 record_unwind_protect_void (unwind_redisplay);
16700 redisplaying_p = true;
16701 block_buffer_flips ();
16702 specbind (Qinhibit_free_realized_faces, Qnil);
16703
16704
16705 record_in_backtrace (Qredisplay_internal_xC_functionx, 0, 0);
16706
16707 FOR_EACH_FRAME (tail, frame)
16708 XFRAME (frame)->already_hscrolled_p = false;
16709
16710 reset_outermost_restrictions ();
16711
16712 retry:
16713
16714 sw = w;
16715
16716 pending = false;
16717 forget_escape_and_glyphless_faces ();
16718
16719 inhibit_free_realized_faces = false;
16720
16721
16722
16723
16724 if (face_change)
16725 windows_or_buffers_changed = 47;
16726
16727 if ((FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf))
16728 && FRAME_TTY (sf)->previous_frame != sf)
16729 {
16730
16731
16732
16733 SET_FRAME_GARBAGED (sf);
16734 #if !defined DOS_NT && !defined HAVE_ANDROID
16735 set_tty_color_mode (FRAME_TTY (sf), sf);
16736 #endif
16737 FRAME_TTY (sf)->previous_frame = sf;
16738 }
16739
16740
16741
16742
16743 number_of_visible_frames = 0;
16744
16745 FOR_EACH_FRAME (tail, frame)
16746 {
16747 struct frame *f = XFRAME (frame);
16748
16749 if (FRAME_REDISPLAY_P (f))
16750 {
16751 ++number_of_visible_frames;
16752
16753 if (f->fonts_changed)
16754 {
16755 adjust_frame_glyphs (f);
16756
16757
16758
16759
16760
16761
16762 SET_FRAME_GARBAGED (f);
16763 f->fonts_changed = false;
16764 }
16765
16766
16767 if (f != sf && f->cursor_type_changed)
16768 fset_redisplay (f);
16769 }
16770 clear_desired_matrices (f);
16771 }
16772
16773
16774 do_pending_window_change (true);
16775
16776
16777 clear_garbaged_frames ();
16778
16779
16780 if (NILP (Vmemory_full))
16781 prepare_menu_bars ();
16782
16783
16784
16785
16786
16787 if (WINDOWP (selected_window) && (w = XWINDOW (selected_window)) != sw)
16788 sw = w;
16789
16790 reconsider_clip_changes (w);
16791
16792
16793 match_p = XBUFFER (w->contents) == current_buffer;
16794 if (match_p)
16795 {
16796
16797 if ((SAVE_MODIFF < MODIFF) != w->last_had_star)
16798 w->update_mode_line = true;
16799
16800 if (mode_line_update_needed (w))
16801 w->update_mode_line = true;
16802
16803
16804
16805
16806 if (current_buffer->clip_changed)
16807 bset_update_mode_line (current_buffer);
16808 }
16809
16810
16811
16812
16813
16814
16815 if ((!NILP (echo_area_buffer[0]) && !display_last_displayed_message_p)
16816 || (!NILP (echo_area_buffer[1]) && display_last_displayed_message_p)
16817 || (message_cleared_p
16818 && minibuf_level == 0
16819
16820
16821 && !MINI_WINDOW_P (XWINDOW (selected_window))))
16822 {
16823 echo_area_display (false);
16824
16825 if (message_cleared_p)
16826 update_miniwindow_p = true;
16827
16828 must_finish = true;
16829
16830
16831
16832
16833
16834 if (!display_last_displayed_message_p)
16835 message_cleared_p = false;
16836 }
16837 else if (EQ (selected_window, minibuf_window)
16838 && (current_buffer->clip_changed || window_outdated (w))
16839 && resize_mini_window (w, false))
16840 {
16841
16842
16843 must_finish = true;
16844
16845
16846
16847
16848 clear_garbaged_frames ();
16849 }
16850
16851 if (!NILP (Vrun_hooks))
16852 run_window_change_functions ();
16853
16854 if (windows_or_buffers_changed && !update_mode_lines)
16855
16856
16857
16858 update_mode_lines = (windows_or_buffers_changed == REDISPLAY_SOME
16859 ? REDISPLAY_SOME : 32);
16860
16861
16862
16863
16864
16865 overlay_arrows_changed_p (true);
16866
16867 consider_all_windows_p = (update_mode_lines
16868 || windows_or_buffers_changed);
16869
16870 #define AINC(a,i) \
16871 { \
16872 Lisp_Object entry = Fgethash (make_fixnum (i), a, make_fixnum (0)); \
16873 if (FIXNUMP (entry)) \
16874 Fputhash (make_fixnum (i), make_fixnum (1 + XFIXNUM (entry)), a); \
16875 }
16876
16877 AINC (Vredisplay__all_windows_cause, windows_or_buffers_changed);
16878 AINC (Vredisplay__mode_lines_cause, update_mode_lines);
16879
16880
16881
16882
16883
16884 tlbufpos = this_line_start_pos;
16885 tlendpos = this_line_end_pos;
16886 if (!consider_all_windows_p
16887 && CHARPOS (tlbufpos) > 0
16888 && !w->update_mode_line
16889 && !current_buffer->clip_changed
16890 && !current_buffer->prevent_redisplay_optimizations_p
16891 && FRAME_REDISPLAY_P (XFRAME (w->frame))
16892 && !FRAME_OBSCURED_P (XFRAME (w->frame))
16893 && !XFRAME (w->frame)->cursor_type_changed
16894 && !XFRAME (w->frame)->face_change
16895
16896 && this_line_buffer == current_buffer
16897 && match_p
16898 && !w->force_start
16899 && !w->optional_new_start
16900
16901 && PT >= CHARPOS (tlbufpos)
16902 && PT <= Z - CHARPOS (tlendpos)
16903
16904
16905
16906
16907
16908
16909 && (NILP (Vdisplay_line_numbers)
16910 || EQ (Vdisplay_line_numbers, Qvisual))
16911
16912
16913 && text_outside_line_unchanged_p (w, CHARPOS (tlbufpos),
16914 CHARPOS (tlendpos)))
16915 {
16916 if (CHARPOS (tlbufpos) > BEGV
16917 && FETCH_BYTE (BYTEPOS (tlbufpos) - 1) != '\n'
16918 && (CHARPOS (tlbufpos) == ZV
16919 || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
16920
16921 goto cancel;
16922 else if (window_outdated (w) || MINI_WINDOW_P (w))
16923 {
16924
16925
16926
16927
16928
16929
16930
16931
16932
16933
16934
16935
16936
16937
16938
16939 struct it it;
16940 int line_height_before = this_line_pixel_height;
16941
16942
16943
16944 start_display (&it, w, tlbufpos);
16945
16946
16947 if (it.current_x != this_line_start_x)
16948 goto cancel;
16949
16950
16951
16952
16953 if (it.sp > 1
16954 && it.method == GET_FROM_IMAGE && it.image_id == -1)
16955 goto cancel;
16956 redisplay_trace ("trying display optimization 1\n");
16957 w->cursor.vpos = -1;
16958 overlay_arrow_seen = false;
16959 it.vpos = this_line_vpos;
16960 it.current_y = this_line_y;
16961 it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos);
16962 display_line (&it, -1);
16963
16964
16965
16966 if (w->cursor.vpos >= 0
16967
16968
16969 && CHARPOS (this_line_start_pos)
16970
16971 && CHARPOS (this_line_end_pos) == CHARPOS (tlendpos)
16972
16973
16974 && this_line_pixel_height == line_height_before
16975
16976
16977
16978
16979 && !hscrolling_current_line_p (w))
16980 {
16981
16982
16983 if (it.current_y < it.last_visible_y)
16984 {
16985 struct glyph_row *row
16986 = MATRIX_ROW (w->current_matrix, this_line_vpos + 1);
16987 ptrdiff_t delta, delta_bytes;
16988
16989
16990
16991
16992
16993
16994 delta = (Z
16995 - CHARPOS (tlendpos)
16996 - MATRIX_ROW_START_CHARPOS (row));
16997 delta_bytes = (Z_BYTE
16998 - BYTEPOS (tlendpos)
16999 - MATRIX_ROW_START_BYTEPOS (row));
17000
17001 increment_matrix_positions (w->current_matrix,
17002 this_line_vpos + 1,
17003 w->current_matrix->nrows,
17004 delta, delta_bytes);
17005 }
17006
17007
17008
17009
17010 if (MATRIX_ROW_DISPLAYS_TEXT_P (it.glyph_row - 1))
17011 {
17012 if (w->window_end_vpos < this_line_vpos)
17013 w->window_end_vpos = this_line_vpos;
17014 }
17015 else if (w->window_end_vpos == this_line_vpos
17016 && this_line_vpos > 0)
17017 w->window_end_vpos = this_line_vpos - 1;
17018 w->window_end_valid = false;
17019
17020
17021 w->desired_matrix->no_scrolling_p = true;
17022
17023 #ifdef GLYPH_DEBUG
17024 *w->desired_matrix->method = 0;
17025 debug_method_add (w, "optimization 1");
17026 #endif
17027 #ifdef HAVE_WINDOW_SYSTEM
17028 update_window_fringes (w, false);
17029 #endif
17030 goto update;
17031 }
17032 else
17033 goto cancel;
17034 }
17035 else if (
17036 PT == w->last_point
17037
17038
17039
17040
17041 && 0 <= w->cursor.vpos
17042 && w->cursor.vpos < WINDOW_TOTAL_LINES (w))
17043 {
17044 if (!must_finish)
17045 {
17046 do_pending_window_change (true);
17047
17048 if (WINDOWP (selected_window)
17049 && (w = XWINDOW (selected_window)) != sw)
17050 goto retry;
17051
17052
17053
17054 if (w->cursor_off_p == w->last_cursor_off_p)
17055 goto end_of_redisplay;
17056 }
17057 goto update;
17058 }
17059
17060
17061 else if (NILP (Vshow_trailing_whitespace)
17062 && !cursor_in_echo_area
17063 && !composition_break_at_point)
17064 {
17065 struct it it;
17066 struct glyph_row *row;
17067
17068
17069
17070
17071 init_iterator (&it, w, CHARPOS (tlbufpos), BYTEPOS (tlbufpos),
17072 NULL, DEFAULT_FACE_ID);
17073 it.current_x = this_line_start_x;
17074 it.current_y = this_line_y;
17075 it.vpos = this_line_vpos;
17076
17077 if (current_buffer->long_line_optimizations_p
17078 && it.line_wrap == TRUNCATE
17079 && PT - CHARPOS (tlbufpos) > large_hscroll_threshold)
17080 {
17081
17082
17083
17084 reseat_at_next_visible_line_start (&it, false);
17085 if (IT_CHARPOS (it) <= PT)
17086 it.vpos = this_line_vpos + 1;
17087 }
17088 else
17089 {
17090
17091
17092 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
17093 }
17094
17095 if (it.vpos == this_line_vpos
17096 && (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
17097 row->enabled_p))
17098 {
17099 eassert (this_line_vpos == it.vpos);
17100 eassert (this_line_y == it.current_y);
17101 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
17102 if (cursor_row_fully_visible_p (w, false, true, false))
17103 {
17104 #ifdef GLYPH_DEBUG
17105 *w->desired_matrix->method = 0;
17106 debug_method_add (w, "optimization 3");
17107 #endif
17108 goto update;
17109 }
17110 else
17111 goto cancel;
17112 }
17113 else
17114 goto cancel;
17115 }
17116
17117 cancel:
17118
17119 SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, false);
17120 }
17121
17122 CHARPOS (this_line_start_pos) = 0;
17123 ++clear_face_cache_count;
17124 #ifdef HAVE_WINDOW_SYSTEM
17125 ++clear_image_cache_count;
17126 #endif
17127
17128
17129
17130
17131
17132
17133 if (consider_all_windows_p)
17134 {
17135 FOR_EACH_FRAME (tail, frame)
17136 XFRAME (frame)->updated_p = false;
17137
17138 propagate_buffer_redisplay ();
17139
17140 FOR_EACH_FRAME (tail, frame)
17141 {
17142 struct frame *f = XFRAME (frame);
17143
17144
17145
17146 if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
17147 && !EQ (FRAME_TTY (f)->top_frame, frame))
17148 continue;
17149
17150 retry_frame:
17151 if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
17152 {
17153 bool gcscrollbars
17154
17155 = f->redisplay || !REDISPLAY_SOME_P ();
17156 bool f_redisplay_flag = f->redisplay;
17157
17158
17159
17160
17161 if (!FRAME_LIVE_P (f))
17162 continue;
17163
17164
17165
17166 if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
17167 FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f);
17168
17169 if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
17170 {
17171
17172
17173
17174
17175
17176
17177
17178 f->inhibit_clear_image_cache = true;
17179 redisplay_windows (FRAME_ROOT_WINDOW (f));
17180 }
17181
17182
17183 else if (!REDISPLAY_SOME_P ())
17184 f->redisplay = true;
17185
17186
17187 if (!FRAME_LIVE_P (f))
17188 continue;
17189
17190
17191
17192 if (gcscrollbars && FRAME_TERMINAL (f)->judge_scroll_bars_hook)
17193 FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
17194
17195 if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
17196 {
17197
17198 if (f->fonts_changed)
17199 {
17200 adjust_frame_glyphs (f);
17201
17202
17203
17204 SET_FRAME_GARBAGED (f);
17205 f->fonts_changed = false;
17206 goto retry_frame;
17207 }
17208
17209
17210 if (!f->already_hscrolled_p)
17211 {
17212 f->already_hscrolled_p = true;
17213 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17214 && hscroll_windows (f->root_window))
17215 {
17216 hscroll_retries++;
17217 goto retry_frame;
17218 }
17219 }
17220
17221
17222
17223
17224
17225
17226
17227
17228
17229
17230
17231
17232 if (!f_redisplay_flag && f->redisplay)
17233 goto retry_frame;
17234
17235
17236
17237
17238
17239
17240
17241
17242
17243 if (FRAME_GARBAGED_P (f)
17244 && garbaged_frame_retries++ < MAX_GARBAGED_FRAME_RETRIES)
17245 goto retry;
17246
17247 #ifdef HAVE_WINDOW_SYSTEM
17248 if (FRAME_WINDOW_P (f)
17249 && FRAME_RIF (f)->clear_under_internal_border)
17250 FRAME_RIF (f)->clear_under_internal_border (f);
17251 #endif
17252
17253
17254
17255 if (interrupt_input)
17256 unrequest_sigio ();
17257 STOP_POLLING;
17258
17259 pending |= update_frame (f, false, false);
17260
17261
17262
17263
17264
17265
17266
17267 if (FRAME_GARBAGED_P (f))
17268 {
17269 fset_redisplay (f);
17270 f->garbaged = false;
17271 goto retry_frame;
17272 }
17273 f->cursor_type_changed = false;
17274 f->updated_p = true;
17275 f->inhibit_clear_image_cache = false;
17276 }
17277 }
17278 }
17279
17280 eassert (EQ (XFRAME (selected_frame)->selected_window, selected_window));
17281
17282 if (!pending)
17283 {
17284
17285
17286
17287 FOR_EACH_FRAME (tail, frame)
17288 {
17289 struct frame *f = XFRAME (frame);
17290 if (f->updated_p)
17291 {
17292 f->redisplay = false;
17293 f->garbaged = false;
17294 mark_window_display_accurate (f->root_window, true);
17295 if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
17296 FRAME_TERMINAL (f)->frame_up_to_date_hook (f);
17297 }
17298 }
17299 }
17300 }
17301 else if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
17302 {
17303 sf->inhibit_clear_image_cache = true;
17304 displayed_buffer = XBUFFER (XWINDOW (selected_window)->contents);
17305
17306
17307 internal_condition_case_1 (redisplay_window_1, selected_window,
17308 list_of_error,
17309 redisplay_window_error);
17310 if (update_miniwindow_p)
17311 {
17312 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
17313
17314 displayed_buffer = XBUFFER (XWINDOW (mini_window)->contents);
17315 internal_condition_case_1 (redisplay_window_1, mini_window,
17316 list_of_error,
17317 redisplay_window_error);
17318 }
17319
17320
17321
17322 update:
17323
17324
17325
17326 if (sf->fonts_changed || sf->redisplay)
17327 {
17328 if (sf->redisplay)
17329 {
17330
17331
17332
17333
17334
17335
17336 windows_or_buffers_changed = 50;
17337 }
17338 goto retry;
17339 }
17340
17341
17342
17343 inhibit_free_realized_faces = true;
17344
17345
17346
17347
17348 if (interrupt_input)
17349 unrequest_sigio ();
17350 STOP_POLLING;
17351
17352 if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
17353 {
17354 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17355 && hscroll_windows (selected_window))
17356 {
17357 hscroll_retries++;
17358 goto retry;
17359 }
17360
17361 XWINDOW (selected_window)->must_be_updated_p = true;
17362 pending = update_frame (sf, false, false);
17363 sf->cursor_type_changed = false;
17364 sf->inhibit_clear_image_cache = false;
17365 }
17366
17367
17368
17369
17370
17371
17372 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
17373 struct frame *mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
17374
17375 if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
17376 {
17377 XWINDOW (mini_window)->must_be_updated_p = true;
17378 pending |= update_frame (mini_frame, false, false);
17379 mini_frame->cursor_type_changed = false;
17380 if (!pending && hscroll_retries <= MAX_HSCROLL_RETRIES
17381 && hscroll_windows (mini_window))
17382 {
17383 hscroll_retries++;
17384 goto retry;
17385 }
17386 }
17387 }
17388
17389
17390
17391 if (pending)
17392 {
17393
17394
17395
17396 CHARPOS (this_line_start_pos) = 0;
17397
17398
17399 update_overlay_arrows (0);
17400
17401
17402
17403 if (!WINDOW_FULL_WIDTH_P (w)
17404 && !FRAME_WINDOW_P (XFRAME (w->frame)))
17405 update_mode_lines = 36;
17406 }
17407 else
17408 {
17409 if (!consider_all_windows_p)
17410 {
17411
17412
17413 if (XBUFFER (w->contents)->text->redisplay
17414 && buffer_window_count (XBUFFER (w->contents)) > 1)
17415
17416
17417 propagate_buffer_redisplay ();
17418 mark_window_display_accurate_1 (w, true);
17419
17420
17421 update_overlay_arrows (1);
17422
17423 if (FRAME_TERMINAL (sf)->frame_up_to_date_hook != 0)
17424 FRAME_TERMINAL (sf)->frame_up_to_date_hook (sf);
17425 }
17426
17427 update_mode_lines = 0;
17428 windows_or_buffers_changed = 0;
17429 }
17430
17431
17432
17433
17434
17435 if (interrupt_input)
17436 request_sigio ();
17437 RESUME_POLLING;
17438
17439
17440
17441
17442
17443
17444
17445 if (!pending)
17446 {
17447 int new_count = 0;
17448
17449 FOR_EACH_FRAME (tail, frame)
17450 {
17451 if (FRAME_REDISPLAY_P (XFRAME (frame)))
17452 new_count++;
17453 }
17454
17455 if (new_count != number_of_visible_frames)
17456 windows_or_buffers_changed = 52;
17457 }
17458
17459
17460 do_pending_window_change (true);
17461
17462
17463
17464 if ((windows_or_buffers_changed && !pending)
17465 || (WINDOWP (selected_window)
17466 && (w = XWINDOW (selected_window)) != sw))
17467 goto retry;
17468
17469
17470
17471
17472
17473
17474
17475 if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
17476 {
17477 clear_face_cache (false);
17478 clear_face_cache_count = 0;
17479 }
17480
17481 #ifdef HAVE_WINDOW_SYSTEM
17482 if (clear_image_cache_count > CLEAR_IMAGE_CACHE_COUNT)
17483 {
17484 clear_image_caches (Qnil);
17485 clear_image_cache_count = 0;
17486 }
17487 #endif
17488
17489 end_of_redisplay:
17490 #ifdef HAVE_NS
17491 ns_set_doc_edited ();
17492 #endif
17493 if (interrupt_input && interrupts_deferred)
17494 request_sigio ();
17495
17496
17497
17498 if (max_redisplay_ticks > 0)
17499 update_redisplay_ticks (0, NULL);
17500
17501 unbind_to (count, Qnil);
17502 RESUME_POLLING;
17503 }
17504
17505 static void
17506 unwind_redisplay_preserve_echo_area (void)
17507 {
17508 unblock_buffer_flips ();
17509 }
17510
17511
17512
17513
17514
17515
17516
17517
17518
17519
17520
17521
17522 void
17523 redisplay_preserve_echo_area (int from_where)
17524 {
17525 redisplay_trace ("redisplay_preserve_echo_area (%d)\n", from_where);
17526
17527 block_input ();
17528 specpdl_ref count = SPECPDL_INDEX ();
17529 record_unwind_protect_void (unwind_redisplay_preserve_echo_area);
17530 block_buffer_flips ();
17531 unblock_input ();
17532
17533 if (!NILP (echo_area_buffer[1]))
17534 {
17535
17536
17537 display_last_displayed_message_p = true;
17538 redisplay_internal ();
17539 display_last_displayed_message_p = false;
17540 }
17541 else
17542 redisplay_internal ();
17543
17544 flush_frame (SELECTED_FRAME ());
17545 unbind_to (count, Qnil);
17546 }
17547
17548
17549
17550
17551 static void
17552 unwind_redisplay (void)
17553 {
17554 redisplaying_p = false;
17555 unblock_buffer_flips ();
17556 }
17557
17558
17559
17560 void
17561 unwind_display_working_on_window (void)
17562 {
17563 display_working_on_window_p = false;
17564 }
17565
17566
17567
17568
17569
17570
17571 static void
17572 mark_window_display_accurate_1 (struct window *w, bool accurate_p)
17573 {
17574 struct buffer *b = XBUFFER (w->contents);
17575 #ifdef HAVE_TEXT_CONVERSION
17576 ptrdiff_t prev_point, prev_mark;
17577 #endif
17578
17579 w->last_modified = accurate_p ? BUF_MODIFF (b) : 0;
17580 w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF (b) : 0;
17581 w->last_had_star = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b);
17582
17583 if (accurate_p)
17584 {
17585 b->clip_changed = false;
17586 b->prevent_redisplay_optimizations_p = false;
17587 eassert (buffer_window_count (b) > 0);
17588
17589
17590
17591 b->text->redisplay = false;
17592
17593 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
17594 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
17595 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
17596 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
17597
17598 w->current_matrix->buffer = b;
17599 w->current_matrix->begv = BUF_BEGV (b);
17600 w->current_matrix->zv = BUF_ZV (b);
17601 w->current_matrix->header_line_p = window_wants_header_line (w);
17602 w->current_matrix->tab_line_p = window_wants_tab_line (w);
17603
17604 w->last_cursor_vpos = w->cursor.vpos;
17605 w->last_cursor_off_p = w->cursor_off_p;
17606
17607 #ifdef HAVE_TEXT_CONVERSION
17608 prev_point = w->last_point;
17609 prev_mark = w->last_mark;
17610 #endif
17611
17612 if (w == XWINDOW (selected_window))
17613 w->last_point = BUF_PT (b);
17614 else
17615 w->last_point = marker_position (w->pointm);
17616
17617
17618
17619
17620
17621 if (XMARKER (BVAR (b, mark))->buffer == b
17622 && !NILP (BVAR (b, mark_active)))
17623 w->last_mark = marker_position (BVAR (b, mark));
17624 else
17625 w->last_mark = -1;
17626
17627 #ifdef HAVE_TEXT_CONVERSION
17628
17629 w->ephemeral_last_point = w->last_point;
17630
17631
17632
17633
17634
17635
17636
17637
17638
17639
17640
17641
17642
17643
17644
17645 if ((prev_point != w->last_point
17646 || prev_mark != w->last_mark)
17647 && FRAME_WINDOW_P (WINDOW_XFRAME (w))
17648 && w == XWINDOW (WINDOW_XFRAME (w)->selected_window))
17649 report_point_change (WINDOW_XFRAME (w), w, b);
17650 #endif
17651
17652 w->window_end_valid = true;
17653 w->update_mode_line = false;
17654 w->preserve_vscroll_p = false;
17655 }
17656
17657 w->redisplay = !accurate_p;
17658 }
17659
17660
17661
17662
17663
17664
17665
17666 void
17667 mark_window_display_accurate (Lisp_Object window, bool accurate_p)
17668 {
17669 struct window *w;
17670
17671 for (; !NILP (window); window = w->next)
17672 {
17673 w = XWINDOW (window);
17674 if (WINDOWP (w->contents))
17675 mark_window_display_accurate (w->contents, accurate_p);
17676 else
17677 mark_window_display_accurate_1 (w, accurate_p);
17678 }
17679
17680 if (accurate_p)
17681 update_overlay_arrows (1);
17682 else
17683
17684
17685
17686 update_overlay_arrows (-1);
17687 }
17688
17689
17690
17691
17692
17693
17694
17695 Lisp_Object
17696 disp_char_vector (struct Lisp_Char_Table *dp, int c)
17697 {
17698 Lisp_Object val;
17699
17700 if (ASCII_CHAR_P (c))
17701 {
17702 val = dp->ascii;
17703 if (SUB_CHAR_TABLE_P (val))
17704 val = XSUB_CHAR_TABLE (val)->contents[c];
17705 }
17706 else
17707 {
17708 Lisp_Object table;
17709
17710 XSETCHAR_TABLE (table, dp);
17711 val = char_table_ref (table, c);
17712 }
17713 if (NILP (val))
17714 val = dp->defalt;
17715 return val;
17716 }
17717
17718 static int buffer_flip_blocked_depth;
17719
17720 static void
17721 block_buffer_flips (void)
17722 {
17723 eassert (buffer_flip_blocked_depth >= 0);
17724 buffer_flip_blocked_depth++;
17725 }
17726
17727 static void
17728 unblock_buffer_flips (void)
17729 {
17730 eassert (buffer_flip_blocked_depth > 0);
17731 if (--buffer_flip_blocked_depth == 0)
17732 {
17733 Lisp_Object tail, frame;
17734 block_input ();
17735 FOR_EACH_FRAME (tail, frame)
17736 {
17737 struct frame *f = XFRAME (frame);
17738 if (FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook)
17739 (*FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook) (f);
17740 }
17741 unblock_input ();
17742 }
17743 }
17744
17745 bool
17746 buffer_flipping_blocked_p (void)
17747 {
17748 return buffer_flip_blocked_depth > 0;
17749 }
17750
17751
17752
17753
17754
17755
17756
17757
17758 static void
17759 redisplay_windows (Lisp_Object window)
17760 {
17761 while (!NILP (window))
17762 {
17763 struct window *w = XWINDOW (window);
17764
17765 if (WINDOWP (w->contents))
17766 redisplay_windows (w->contents);
17767 else if (BUFFERP (w->contents))
17768 {
17769 displayed_buffer = XBUFFER (w->contents);
17770
17771
17772 internal_condition_case_1 (redisplay_window_0, window,
17773 list_of_error,
17774 redisplay_window_error);
17775 }
17776
17777 window = w->next;
17778 }
17779 }
17780
17781 static Lisp_Object
17782 redisplay_window_error (Lisp_Object error_data)
17783 {
17784 displayed_buffer->display_error_modiff = BUF_MODIFF (displayed_buffer);
17785
17786
17787
17788 if (max_redisplay_ticks > 0
17789 && CONSP (error_data)
17790 && EQ (XCAR (error_data), Qerror)
17791 && STRINGP (XCAR (XCDR (error_data))))
17792 Vdelayed_warnings_list = Fcons (list2 (XCAR (error_data),
17793 XCAR (XCDR (error_data))),
17794 Vdelayed_warnings_list);
17795 return Qnil;
17796 }
17797
17798 static Lisp_Object
17799 redisplay_window_0 (Lisp_Object window)
17800 {
17801 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
17802 redisplay_window (window, false);
17803 return Qnil;
17804 }
17805
17806 static Lisp_Object
17807 redisplay_window_1 (Lisp_Object window)
17808 {
17809 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
17810 redisplay_window (window, true);
17811 return Qnil;
17812 }
17813
17814
17815
17816
17817
17818
17819
17820
17821
17822
17823
17824
17825
17826
17827
17828
17829
17830
17831
17832 void
17833 update_redisplay_ticks (int ticks, struct window *w)
17834 {
17835
17836 static struct window *cwindow;
17837 static EMACS_INT window_ticks;
17838
17839
17840
17841
17842 if (!ticks && w != cwindow)
17843 {
17844 cwindow = w;
17845 window_ticks = 0;
17846 }
17847
17848
17849 if ((!w && !redisplaying_p && !display_working_on_window_p)
17850
17851
17852 || (w && MINI_WINDOW_P (w)))
17853 return;
17854
17855 if (ticks > 0)
17856 window_ticks += ticks;
17857 if (max_redisplay_ticks > 0 && window_ticks > max_redisplay_ticks)
17858 {
17859
17860
17861
17862 Lisp_Object contents = w ? w->contents : Qnil;
17863 char *bufname =
17864 NILP (contents)
17865 ? SSDATA (BVAR (current_buffer, name))
17866 : (BUFFERP (contents)
17867 ? SSDATA (BVAR (XBUFFER (contents), name))
17868 : (char *) "<unknown>");
17869
17870 windows_or_buffers_changed = 177;
17871
17872
17873
17874 if (w && w->desired_matrix)
17875 w->desired_matrix->no_scrolling_p = true;
17876 error ("Window showing buffer %s takes too long to redisplay", bufname);
17877 }
17878 }
17879
17880
17881
17882
17883
17884
17885
17886
17887
17888
17889 static bool
17890 set_cursor_from_row (struct window *w, struct glyph_row *row,
17891 struct glyph_matrix *matrix,
17892 ptrdiff_t delta, ptrdiff_t delta_bytes,
17893 int dy, int dvpos)
17894 {
17895 struct glyph *glyph = row->glyphs[TEXT_AREA];
17896 struct glyph *end = glyph + row->used[TEXT_AREA];
17897 struct glyph *cursor = NULL;
17898
17899 ptrdiff_t last_pos = MATRIX_ROW_START_CHARPOS (row) + delta;
17900 int x = row->x;
17901 ptrdiff_t pt_old = PT - delta;
17902 ptrdiff_t pos_before = MATRIX_ROW_START_CHARPOS (row) + delta;
17903 ptrdiff_t pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
17904 struct glyph *glyph_before = glyph - 1, *glyph_after = end;
17905
17906
17907 struct glyph *glyphs_end = end;
17908
17909
17910 bool match_with_avoid_cursor = false;
17911
17912
17913 bool string_seen = false;
17914
17915
17916 ptrdiff_t bpos_max = pos_before;
17917 ptrdiff_t bpos_min = pos_after;
17918
17919
17920 ptrdiff_t bpos_covered = 0;
17921
17922
17923 bool string_from_text_prop = false;
17924
17925
17926
17927
17928 eassert (!row->mode_line_p);
17929 if (row->mode_line_p)
17930 return false;
17931
17932
17933
17934
17935 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
17936 {
17937 if (!row->reversed_p)
17938 {
17939 while (glyph < end
17940 && NILP (glyph->object)
17941 && glyph->charpos < 0)
17942 {
17943 x += glyph->pixel_width;
17944 ++glyph;
17945 }
17946 while (end > glyph
17947 && NILP ((end - 1)->object)
17948
17949
17950 && (end - 1)->charpos <= 0)
17951 --end;
17952 glyph_before = glyph - 1;
17953 glyph_after = end;
17954 }
17955 else
17956 {
17957 struct glyph *g;
17958
17959
17960
17961 glyphs_end = end = glyph - 1;
17962 glyph += row->used[TEXT_AREA] - 1;
17963
17964 while (glyph > end + 1
17965 && NILP (glyph->object)
17966 && glyph->charpos < 0)
17967 --glyph;
17968 if (NILP (glyph->object) && glyph->charpos < 0)
17969 --glyph;
17970
17971
17972 for (x = 0, g = end + 1; g < glyph; g++)
17973 x += g->pixel_width;
17974 while (end < glyph
17975 && NILP ((end + 1)->object)
17976 && (end + 1)->charpos <= 0)
17977 ++end;
17978 glyph_before = glyph + 1;
17979 glyph_after = end;
17980 }
17981 }
17982 else if (row->reversed_p)
17983 {
17984
17985
17986
17987 cursor = end - 1;
17988
17989
17990
17991 if (!FRAME_WINDOW_P (WINDOW_XFRAME (w))
17992 && !WINDOW_RIGHTMOST_P (w)
17993 && cursor == row->glyphs[LAST_AREA] - 1)
17994 cursor--;
17995 x = -1;
17996 }
17997
17998
17999
18000
18001
18002 if (!row->reversed_p)
18003 while (
18004 glyph < end
18005
18006 && !NILP (glyph->object))
18007 {
18008 if (BUFFERP (glyph->object))
18009 {
18010 ptrdiff_t dpos = glyph->charpos - pt_old;
18011
18012 if (glyph->charpos > bpos_max)
18013 bpos_max = glyph->charpos;
18014 if (glyph->charpos < bpos_min)
18015 bpos_min = glyph->charpos;
18016 if (!glyph->avoid_cursor_p)
18017 {
18018
18019
18020 if (dpos == 0)
18021 {
18022 match_with_avoid_cursor = false;
18023 break;
18024 }
18025
18026
18027 if (0 > dpos && dpos > pos_before - pt_old)
18028 {
18029 pos_before = glyph->charpos;
18030 glyph_before = glyph;
18031 }
18032 else if (0 < dpos && dpos < pos_after - pt_old)
18033 {
18034 pos_after = glyph->charpos;
18035 glyph_after = glyph;
18036 }
18037 }
18038 else if (dpos == 0)
18039 match_with_avoid_cursor = true;
18040 }
18041 else if (STRINGP (glyph->object))
18042 {
18043 Lisp_Object chprop;
18044 ptrdiff_t glyph_pos = glyph->charpos;
18045
18046 chprop = Fget_char_property (make_fixnum (glyph_pos), Qcursor,
18047 glyph->object);
18048 if (!NILP (chprop))
18049 {
18050
18051
18052
18053
18054
18055
18056
18057
18058
18059
18060 ptrdiff_t prop_pos =
18061 string_buffer_position_lim (glyph->object, pos_before,
18062 pos_after, false);
18063
18064 if (prop_pos >= pos_before)
18065 bpos_max = prop_pos;
18066 }
18067 if (FIXNUMP (chprop))
18068 {
18069 bpos_covered = bpos_max + XFIXNUM (chprop);
18070
18071
18072
18073
18074
18075
18076
18077
18078
18079
18080
18081 if (bpos_max <= pt_old && bpos_covered >= pt_old)
18082 {
18083 cursor = glyph;
18084 break;
18085 }
18086 }
18087
18088 string_seen = true;
18089 }
18090 x += glyph->pixel_width;
18091 ++glyph;
18092 }
18093 else if (glyph > end)
18094 while (!NILP (glyph->object))
18095 {
18096 if (BUFFERP (glyph->object))
18097 {
18098 ptrdiff_t dpos = glyph->charpos - pt_old;
18099
18100 if (glyph->charpos > bpos_max)
18101 bpos_max = glyph->charpos;
18102 if (glyph->charpos < bpos_min)
18103 bpos_min = glyph->charpos;
18104 if (!glyph->avoid_cursor_p)
18105 {
18106 if (dpos == 0)
18107 {
18108 match_with_avoid_cursor = false;
18109 break;
18110 }
18111 if (0 > dpos && dpos > pos_before - pt_old)
18112 {
18113 pos_before = glyph->charpos;
18114 glyph_before = glyph;
18115 }
18116 else if (0 < dpos && dpos < pos_after - pt_old)
18117 {
18118 pos_after = glyph->charpos;
18119 glyph_after = glyph;
18120 }
18121 }
18122 else if (dpos == 0)
18123 match_with_avoid_cursor = true;
18124 }
18125 else if (STRINGP (glyph->object))
18126 {
18127 Lisp_Object chprop;
18128 ptrdiff_t glyph_pos = glyph->charpos;
18129
18130 chprop = Fget_char_property (make_fixnum (glyph_pos), Qcursor,
18131 glyph->object);
18132 if (!NILP (chprop))
18133 {
18134 ptrdiff_t prop_pos =
18135 string_buffer_position_lim (glyph->object, pos_before,
18136 pos_after, false);
18137
18138 if (prop_pos >= pos_before)
18139 bpos_max = prop_pos;
18140 }
18141 if (FIXNUMP (chprop))
18142 {
18143 bpos_covered = bpos_max + XFIXNUM (chprop);
18144
18145
18146
18147 if (bpos_max <= pt_old && bpos_covered >= pt_old)
18148 {
18149 cursor = glyph;
18150 break;
18151 }
18152 }
18153 string_seen = true;
18154 }
18155 --glyph;
18156 if (glyph == glyphs_end)
18157 {
18158 x--;
18159 break;
18160 }
18161 x -= glyph->pixel_width;
18162 }
18163
18164
18165
18166
18167 if (!((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
18168 && BUFFERP (glyph->object) && glyph->charpos == pt_old)
18169 && !(bpos_max <= pt_old && pt_old <= bpos_covered))
18170 {
18171
18172
18173
18174
18175
18176 bool empty_line_p =
18177 ((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
18178 && NILP (glyph->object) && glyph->charpos > 0
18179
18180
18181
18182
18183 && !(row->continued_p || row->truncated_on_right_p));
18184
18185 if (row->ends_in_ellipsis_p && pos_after == last_pos)
18186 {
18187 ptrdiff_t ellipsis_pos;
18188
18189
18190 if (!row->reversed_p)
18191 {
18192 ellipsis_pos = (glyph - 1)->charpos;
18193 while (glyph > row->glyphs[TEXT_AREA]
18194 && (glyph - 1)->charpos == ellipsis_pos)
18195 glyph--, x -= glyph->pixel_width;
18196
18197
18198
18199 x += glyph->pixel_width;
18200 glyph++;
18201 }
18202 else
18203 {
18204 ellipsis_pos = (glyph + 1)->charpos;
18205 while (glyph < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18206 && (glyph + 1)->charpos == ellipsis_pos)
18207 glyph++, x += glyph->pixel_width;
18208 x -= glyph->pixel_width;
18209 glyph--;
18210 }
18211 }
18212 else if (match_with_avoid_cursor)
18213 {
18214 cursor = glyph_after;
18215 x = -1;
18216 }
18217 else if (string_seen)
18218 {
18219 int incr = row->reversed_p ? -1 : +1;
18220
18221
18222
18223
18224
18225
18226 struct glyph *start, *stop;
18227 ptrdiff_t pos = pos_before;
18228
18229 x = -1;
18230
18231
18232
18233
18234
18235
18236 if (row->ends_in_newline_from_string_p)
18237 {
18238 glyph_after = end;
18239 pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
18240 }
18241
18242
18243
18244
18245
18246
18247
18248
18249
18250 if (!row->reversed_p)
18251 {
18252 start = min (glyph_before, glyph_after);
18253 stop = max (glyph_before, glyph_after);
18254 }
18255 else
18256 {
18257 start = max (glyph_before, glyph_after);
18258 stop = min (glyph_before, glyph_after);
18259 }
18260 for (glyph = start + incr;
18261 row->reversed_p ? glyph > stop : glyph < stop; )
18262 {
18263
18264
18265
18266
18267 if (STRINGP (glyph->object))
18268 {
18269 Lisp_Object str;
18270 ptrdiff_t tem;
18271
18272
18273 ptrdiff_t lim = pos_after
18274 + (pos_after == MATRIX_ROW_END_CHARPOS (row) + delta);
18275
18276 string_from_text_prop = false;
18277 str = glyph->object;
18278 tem = string_buffer_position_lim (str, pos, lim, false);
18279 if (tem == 0
18280 || pos <= tem)
18281 {
18282
18283
18284
18285
18286
18287
18288
18289
18290
18291
18292 if (tem == 0
18293 || tem == pt_old
18294 || (tem - pt_old > 0 && tem < pos_after))
18295 {
18296
18297
18298
18299
18300
18301
18302 ptrdiff_t strpos = glyph->charpos;
18303
18304 if (tem)
18305 {
18306 cursor = glyph;
18307 string_from_text_prop = true;
18308 }
18309 for ( ;
18310 (row->reversed_p ? glyph > stop : glyph < stop)
18311 && EQ (glyph->object, str);
18312 glyph += incr)
18313 {
18314 Lisp_Object cprop;
18315 ptrdiff_t gpos = glyph->charpos;
18316
18317 cprop = Fget_char_property (make_fixnum (gpos),
18318 Qcursor,
18319 glyph->object);
18320 if (!NILP (cprop))
18321 {
18322 cursor = glyph;
18323 break;
18324 }
18325 if (tem && glyph->charpos < strpos)
18326 {
18327 strpos = glyph->charpos;
18328 cursor = glyph;
18329 }
18330 }
18331
18332 if (tem == pt_old
18333 || (tem - pt_old > 0 && tem < pos_after))
18334 goto compute_x;
18335 }
18336 if (tem)
18337 pos = tem + 1;
18338 }
18339
18340
18341 while ((row->reversed_p ? glyph > stop : glyph < stop)
18342 && EQ (glyph->object, str))
18343 glyph += incr;
18344 }
18345 else
18346 glyph += incr;
18347 }
18348
18349
18350
18351 if (cursor == NULL
18352 && (row->reversed_p ? glyph <= end : glyph >= end)
18353 && (row->reversed_p ? end > glyphs_end : end < glyphs_end)
18354 && STRINGP (end->object)
18355 && row->continued_p)
18356 return false;
18357 }
18358
18359
18360
18361
18362
18363 else if (row->truncated_on_left_p && pt_old < bpos_min)
18364 {
18365 cursor = glyph_before;
18366 x = -1;
18367 }
18368 else if ((row->truncated_on_right_p && pt_old > bpos_max)
18369
18370 || (!empty_line_p
18371 && (row->reversed_p
18372 ? glyph_after > glyphs_end
18373 : glyph_after < glyphs_end)))
18374 {
18375 cursor = glyph_after;
18376 x = -1;
18377 }
18378 }
18379
18380 compute_x:
18381 if (cursor != NULL)
18382 glyph = cursor;
18383 else if (glyph == glyphs_end
18384 && pos_before == pos_after
18385 && STRINGP ((row->reversed_p
18386 ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18387 : row->glyphs[TEXT_AREA])->object))
18388 {
18389
18390
18391
18392
18393 glyph =
18394 row->reversed_p
18395 ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18396 : row->glyphs[TEXT_AREA];
18397 }
18398 if (x < 0)
18399 {
18400 struct glyph *g;
18401
18402
18403 for (g = row->glyphs[TEXT_AREA], x = row->x; g < glyph; g++)
18404 {
18405 if (g >= row->glyphs[TEXT_AREA] + row->used[TEXT_AREA])
18406 emacs_abort ();
18407 x += g->pixel_width;
18408 }
18409 }
18410
18411
18412
18413
18414
18415
18416 if (
18417 w->cursor.vpos >= 0
18418
18419 && MATRIX_ROW (matrix, w->cursor.vpos) != row
18420
18421
18422
18423
18424
18425 && MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos)) <= pt_old
18426 && pt_old <= MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18427 && cursor_row_p (MATRIX_ROW (matrix, w->cursor.vpos)))
18428 {
18429 struct glyph *g1
18430 = MATRIX_ROW_GLYPH_START (matrix, w->cursor.vpos) + w->cursor.hpos;
18431
18432
18433 if (!(row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end))
18434 return false;
18435
18436
18437 if (
18438 w->cursor.hpos >= 0
18439 && w->cursor.hpos < MATRIX_ROW_USED (matrix, w->cursor.vpos)
18440 && ((BUFFERP (g1->object)
18441 && (g1->charpos == pt_old
18442 || (BUFFERP (glyph->object)
18443 && eabs (g1->charpos - pt_old)
18444 < eabs (glyph->charpos - pt_old))))
18445
18446
18447 || (STRINGP (g1->object)
18448 && (!NILP (Fget_char_property (make_fixnum (g1->charpos),
18449 Qcursor, g1->object))
18450
18451
18452
18453 || (EQ (g1->object, glyph->object)
18454 && string_from_text_prop)
18455
18456
18457 || (NILP (glyph->object)
18458 && glyph->charpos != pt_old)))))
18459 return false;
18460
18461 if (!((BUFFERP (glyph->object) && glyph->charpos == pt_old)
18462
18463
18464
18465 || (!row->continued_p
18466 && NILP (glyph->object)
18467 && glyph->charpos == 0
18468 && pt_old == MATRIX_ROW_END_CHARPOS (row) - 1))
18469
18470
18471
18472
18473
18474 && MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18475 - MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18476 < MATRIX_ROW_END_CHARPOS (row) - MATRIX_ROW_START_CHARPOS (row))
18477 return false;
18478 }
18479 w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
18480 w->cursor.x = x;
18481 w->cursor.vpos = MATRIX_ROW_VPOS (row, matrix) + dvpos;
18482 w->cursor.y = row->y + dy;
18483
18484 if (w == XWINDOW (selected_window))
18485 {
18486 if (!row->continued_p
18487 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
18488 && row->x == 0)
18489 {
18490 this_line_buffer = XBUFFER (w->contents);
18491
18492 CHARPOS (this_line_start_pos)
18493 = MATRIX_ROW_START_CHARPOS (row) + delta;
18494 BYTEPOS (this_line_start_pos)
18495 = MATRIX_ROW_START_BYTEPOS (row) + delta_bytes;
18496
18497 CHARPOS (this_line_end_pos)
18498 = Z - (MATRIX_ROW_END_CHARPOS (row) + delta);
18499 BYTEPOS (this_line_end_pos)
18500 = Z_BYTE - (MATRIX_ROW_END_BYTEPOS (row) + delta_bytes);
18501
18502 this_line_y = w->cursor.y;
18503 this_line_pixel_height = row->height;
18504 this_line_vpos = w->cursor.vpos;
18505 this_line_start_x = row->x;
18506 }
18507 else
18508 CHARPOS (this_line_start_pos) = 0;
18509 }
18510
18511 return true;
18512 }
18513
18514
18515
18516
18517
18518
18519
18520 static struct text_pos
18521 run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
18522 {
18523 struct window *w = XWINDOW (window);
18524 SET_MARKER_FROM_TEXT_POS (w->start, startp);
18525
18526 eassert (current_buffer == XBUFFER (w->contents));
18527
18528 if (!NILP (Vwindow_scroll_functions))
18529 {
18530 specpdl_ref count = SPECPDL_INDEX ();
18531 specbind (Qinhibit_quit, Qt);
18532 safe_run_hooks_2
18533 (Qwindow_scroll_functions, window, make_fixnum (CHARPOS (startp)));
18534 unbind_to (count, Qnil);
18535 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18536
18537 set_buffer_internal (XBUFFER (w->contents));
18538 }
18539
18540 return startp;
18541 }
18542
18543
18544
18545
18546
18547
18548
18549
18550
18551
18552
18553
18554
18555
18556
18557
18558
18559
18560
18561
18562
18563
18564 static bool
18565 cursor_row_fully_visible_p (struct window *w, bool force_p,
18566 bool current_matrix_p,
18567 bool just_test_user_preference_p)
18568 {
18569 struct glyph_matrix *matrix;
18570 struct glyph_row *row;
18571 int window_height;
18572 Lisp_Object mclfv_p =
18573 buffer_local_value (Qmake_cursor_line_fully_visible, w->contents);
18574
18575
18576 if (BASE_EQ (mclfv_p, Qunbound))
18577 mclfv_p = Vmake_cursor_line_fully_visible;
18578
18579
18580 if (FUNCTIONP (mclfv_p))
18581 {
18582 Lisp_Object window;
18583 XSETWINDOW (window, w);
18584
18585
18586 Lisp_Object val = safe_call1 (mclfv_p, window);
18587 if (NILP (val))
18588 return true;
18589 else if (just_test_user_preference_p)
18590 return false;
18591 }
18592 else if (NILP (mclfv_p))
18593 return true;
18594 else if (just_test_user_preference_p)
18595 return false;
18596
18597
18598
18599 if (w->cursor.vpos < 0)
18600 return true;
18601
18602 matrix = current_matrix_p ? w->current_matrix : w->desired_matrix;
18603 row = MATRIX_ROW (matrix, w->cursor.vpos);
18604
18605
18606 if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row))
18607 return true;
18608
18609
18610
18611 window_height = window_box_height (w);
18612 if (row->height >= window_height)
18613 {
18614 if (!force_p || MINI_WINDOW_P (w)
18615 || w->vscroll || w->cursor.vpos == 0)
18616 return true;
18617 }
18618 return false;
18619 }
18620
18621
18622
18623
18624
18625
18626
18627
18628
18629
18630
18631
18632
18633
18634
18635
18636
18637
18638
18639
18640 enum
18641 {
18642 SCROLLING_SUCCESS = 1,
18643 SCROLLING_FAILED = 0,
18644 SCROLLING_NEED_LARGER_MATRICES = -1
18645 };
18646
18647
18648
18649
18650
18651 #define SCROLL_LIMIT 100
18652
18653 static int
18654 try_scrolling (Lisp_Object window, bool just_this_one_p,
18655 intmax_t arg_scroll_conservatively, intmax_t scroll_step,
18656 bool temp_scroll_step, bool last_line_misfit)
18657 {
18658 struct window *w = XWINDOW (window);
18659 struct text_pos pos, startp;
18660 struct it it;
18661 int this_scroll_margin, scroll_max, rc, height;
18662 int dy = 0, amount_to_scroll = 0;
18663 bool scroll_down_p = false;
18664 int extra_scroll_margin_lines = last_line_misfit;
18665 Lisp_Object aggressive;
18666
18667 int scroll_limit = SCROLL_LIMIT;
18668 int frame_line_height = default_line_pixel_height (w);
18669
18670 #ifdef GLYPH_DEBUG
18671 debug_method_add (w, "try_scrolling");
18672 #endif
18673
18674 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18675
18676 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
18677
18678
18679
18680
18681
18682 if (arg_scroll_conservatively > scroll_limit)
18683 {
18684 arg_scroll_conservatively = scroll_limit + 1;
18685 scroll_max = scroll_limit * frame_line_height;
18686 }
18687 else if (0 < scroll_step || 0 < arg_scroll_conservatively || temp_scroll_step)
18688
18689
18690 {
18691 intmax_t scroll_lines_max
18692 = max (scroll_step, max (arg_scroll_conservatively, temp_scroll_step));
18693 int scroll_lines = clip_to_bounds (0, scroll_lines_max, 1000000);
18694 scroll_max = scroll_lines * frame_line_height;
18695 }
18696 else if (NUMBERP (BVAR (current_buffer, scroll_down_aggressively))
18697 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively)))
18698
18699
18700 scroll_max = 10 * frame_line_height;
18701 else
18702 scroll_max = 0;
18703
18704 too_near_end:
18705
18706
18707 if (PT > CHARPOS (startp))
18708 {
18709 int scroll_margin_y;
18710
18711
18712
18713 start_display (&it, w, startp);
18714 scroll_margin_y = it.last_visible_y - partial_line_height (&it)
18715 - this_scroll_margin
18716 - frame_line_height * extra_scroll_margin_lines;
18717 move_it_to (&it, PT, -1, scroll_margin_y - 1, -1,
18718 (MOVE_TO_POS | MOVE_TO_Y));
18719
18720 if (PT > CHARPOS (it.current.pos))
18721 {
18722 int y0 = line_bottom_y (&it);
18723
18724
18725
18726
18727
18728 int slack = max (scroll_max, 10 * frame_line_height);
18729 int y_to_move = it.last_visible_y + slack;
18730
18731
18732
18733
18734
18735 move_it_to (&it, PT, -1, y_to_move,
18736 -1, MOVE_TO_POS | MOVE_TO_Y);
18737 dy = line_bottom_y (&it) - y0;
18738
18739 if (dy > scroll_max)
18740 return SCROLLING_FAILED;
18741
18742 if (dy > 0)
18743 scroll_down_p = true;
18744 }
18745 else if (PT == IT_CHARPOS (it)
18746 && IT_CHARPOS (it) < ZV
18747 && it.method == GET_FROM_STRING
18748 && arg_scroll_conservatively > scroll_limit
18749 && it.current_x == 0)
18750 {
18751 enum move_it_result skip;
18752 int y1 = it.current_y;
18753 int vpos;
18754
18755
18756
18757
18758
18759
18760
18761 do {
18762 skip = move_it_in_display_line_to (&it, ZV, -1, MOVE_TO_POS);
18763 if (skip != MOVE_NEWLINE_OR_CR
18764 || IT_CHARPOS (it) != PT
18765 || it.method == GET_FROM_BUFFER)
18766 break;
18767 vpos = it.vpos;
18768 move_it_to (&it, -1, -1, -1, vpos + 1, MOVE_TO_VPOS);
18769 } while (it.vpos > vpos);
18770
18771 dy = it.current_y - y1;
18772
18773 if (dy > scroll_max)
18774 return SCROLLING_FAILED;
18775
18776 if (dy > 0)
18777 scroll_down_p = true;
18778 }
18779 }
18780
18781 if (scroll_down_p)
18782 {
18783
18784
18785
18786
18787 if (arg_scroll_conservatively)
18788 amount_to_scroll
18789 = min (max (dy, frame_line_height),
18790 frame_line_height * arg_scroll_conservatively);
18791 else if (scroll_step || temp_scroll_step)
18792 amount_to_scroll = scroll_max;
18793 else
18794 {
18795 aggressive = BVAR (current_buffer, scroll_up_aggressively);
18796 height = WINDOW_BOX_TEXT_HEIGHT (w);
18797 if (NUMBERP (aggressive))
18798 {
18799 double float_amount = XFLOATINT (aggressive) * height;
18800 int aggressive_scroll = float_amount;
18801 if (aggressive_scroll == 0 && float_amount > 0)
18802 aggressive_scroll = 1;
18803
18804
18805
18806
18807
18808
18809 if (aggressive_scroll + 2 * this_scroll_margin > height)
18810 aggressive_scroll = height - 2 * this_scroll_margin;
18811 amount_to_scroll = dy + aggressive_scroll;
18812 }
18813 }
18814
18815 if (amount_to_scroll <= 0)
18816 return SCROLLING_FAILED;
18817
18818 start_display (&it, w, startp);
18819 if (arg_scroll_conservatively <= scroll_limit)
18820 move_it_vertically (&it, amount_to_scroll);
18821 else
18822 {
18823
18824
18825
18826
18827
18828
18829 struct it it1;
18830 void *it1data = NULL;
18831
18832
18833 int start_y;
18834
18835 SAVE_IT (it1, it, it1data);
18836 start_y = line_bottom_y (&it1);
18837 do {
18838 RESTORE_IT (&it, &it, it1data);
18839 move_it_by_lines (&it, 1);
18840 SAVE_IT (it1, it, it1data);
18841 } while (IT_CHARPOS (it) < ZV
18842 && line_bottom_y (&it1) - start_y < amount_to_scroll);
18843 bidi_unshelve_cache (it1data, true);
18844 }
18845
18846
18847 if (IT_CHARPOS (it) == CHARPOS (startp))
18848 move_it_by_lines (&it, 1);
18849 startp = it.current.pos;
18850 }
18851 else
18852 {
18853 struct text_pos scroll_margin_pos = startp;
18854 int y_offset = 0;
18855
18856
18857
18858 if (this_scroll_margin)
18859 {
18860 int y_start;
18861
18862 start_display (&it, w, startp);
18863 y_start = it.current_y;
18864 move_it_vertically (&it, this_scroll_margin);
18865 scroll_margin_pos = it.current.pos;
18866
18867
18868
18869 if (IT_CHARPOS (it) == ZV
18870 && it.current_y - y_start < this_scroll_margin)
18871 y_offset = this_scroll_margin - (it.current_y - y_start);
18872 }
18873
18874 if (PT < CHARPOS (scroll_margin_pos))
18875 {
18876
18877
18878 int y0, y_to_move;
18879
18880
18881
18882
18883
18884
18885 SET_TEXT_POS (pos, PT, PT_BYTE);
18886 start_display (&it, w, pos);
18887 y0 = it.current_y;
18888 y_to_move = max (it.last_visible_y,
18889 max (scroll_max, 10 * frame_line_height));
18890 move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
18891 y_to_move, -1,
18892 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
18893 dy = it.current_y - y0;
18894 if (dy > scroll_max
18895 || IT_CHARPOS (it) < CHARPOS (scroll_margin_pos))
18896 return SCROLLING_FAILED;
18897
18898
18899 dy += y_offset;
18900
18901
18902 start_display (&it, w, startp);
18903
18904 if (arg_scroll_conservatively)
18905 amount_to_scroll
18906 = min (max (dy, frame_line_height),
18907 frame_line_height * arg_scroll_conservatively);
18908 else if (scroll_step || temp_scroll_step)
18909 amount_to_scroll = scroll_max;
18910 else
18911 {
18912 aggressive = BVAR (current_buffer, scroll_down_aggressively);
18913 height = WINDOW_BOX_TEXT_HEIGHT (w);
18914 if (NUMBERP (aggressive))
18915 {
18916 double float_amount = XFLOATINT (aggressive) * height;
18917 int aggressive_scroll = float_amount;
18918 if (aggressive_scroll == 0 && float_amount > 0)
18919 aggressive_scroll = 1;
18920
18921
18922
18923
18924 if (aggressive_scroll + 2 * this_scroll_margin > height)
18925 aggressive_scroll = height - 2 * this_scroll_margin;
18926 amount_to_scroll = dy + aggressive_scroll;
18927 }
18928 }
18929
18930 if (amount_to_scroll <= 0)
18931 return SCROLLING_FAILED;
18932
18933 move_it_vertically_backward (&it, amount_to_scroll);
18934 startp = it.current.pos;
18935 }
18936 }
18937
18938
18939 startp = run_window_scroll_functions (window, startp);
18940
18941
18942
18943 if (!try_window (window, startp, 0))
18944 rc = SCROLLING_NEED_LARGER_MATRICES;
18945 else if (w->cursor.vpos < 0)
18946 {
18947 clear_glyph_matrix (w->desired_matrix);
18948 rc = SCROLLING_FAILED;
18949 }
18950 else
18951 {
18952
18953 if (!just_this_one_p
18954 || current_buffer->clip_changed
18955 || BEG_UNCHANGED < CHARPOS (startp))
18956 w->base_line_number = 0;
18957
18958
18959
18960 if (! cursor_row_fully_visible_p (w, extra_scroll_margin_lines <= 1,
18961 false, false)
18962
18963
18964
18965 && extra_scroll_margin_lines < w->desired_matrix->nrows - 1)
18966 {
18967 clear_glyph_matrix (w->desired_matrix);
18968 ++extra_scroll_margin_lines;
18969 goto too_near_end;
18970 }
18971 rc = SCROLLING_SUCCESS;
18972 }
18973
18974 return rc;
18975 }
18976
18977
18978
18979
18980
18981
18982
18983
18984
18985
18986
18987
18988 static bool
18989 compute_window_start_on_continuation_line (struct window *w)
18990 {
18991 struct text_pos pos, start_pos, pos_before_pt;
18992 bool window_start_changed_p = false;
18993
18994 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
18995
18996
18997
18998
18999 if (CHARPOS (start_pos) > BEGV
19000 && FETCH_BYTE (BYTEPOS (start_pos) - 1) != '\n')
19001 {
19002 struct it it;
19003 struct glyph_row *row;
19004
19005
19006 if (CHARPOS (start_pos) < BEGV)
19007 SET_TEXT_POS (start_pos, BEGV, BEGV_BYTE);
19008 else if (CHARPOS (start_pos) > ZV)
19009 SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
19010
19011
19012
19013 row = w->desired_matrix->rows + window_wants_tab_line (w)
19014 + window_wants_header_line (w);
19015 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
19016 row, DEFAULT_FACE_ID);
19017 reseat_at_previous_visible_line_start (&it);
19018
19019
19020
19021
19022
19023
19024
19025 if (IT_CHARPOS (it) <= PT
19026 && (CHARPOS (start_pos) - IT_CHARPOS (it)
19027
19028 < WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w)))
19029 {
19030 int min_distance, distance;
19031
19032
19033
19034
19035
19036
19037
19038 pos_before_pt = pos = it.current.pos;
19039 min_distance = DISP_INFINITY;
19040 while ((distance = eabs (CHARPOS (start_pos) - IT_CHARPOS (it))),
19041 distance < min_distance)
19042 {
19043 min_distance = distance;
19044 if (CHARPOS (pos) <= PT)
19045 pos_before_pt = pos;
19046 pos = it.current.pos;
19047 if (it.line_wrap == WORD_WRAP)
19048 {
19049
19050
19051
19052
19053
19054
19055
19056
19057
19058 move_it_to (&it, ZV, it.last_visible_x, it.current_y, -1,
19059 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19060 move_it_to (&it, ZV, 0,
19061 it.current_y + it.max_ascent + it.max_descent, -1,
19062 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19063 }
19064 else
19065 move_it_by_lines (&it, 1);
19066 }
19067
19068
19069
19070
19071
19072 if (CHARPOS (pos) > PT)
19073 pos = pos_before_pt;
19074
19075
19076 SET_MARKER_FROM_TEXT_POS (w->start, pos);
19077 window_start_changed_p = true;
19078 }
19079 }
19080
19081 return window_start_changed_p;
19082 }
19083
19084
19085
19086
19087
19088
19089
19090
19091
19092
19093
19094
19095
19096
19097
19098
19099
19100 enum
19101 {
19102 CURSOR_MOVEMENT_SUCCESS,
19103 CURSOR_MOVEMENT_CANNOT_BE_USED,
19104 CURSOR_MOVEMENT_MUST_SCROLL,
19105 CURSOR_MOVEMENT_NEED_LARGER_MATRICES
19106 };
19107
19108 static int
19109 try_cursor_movement (Lisp_Object window, struct text_pos startp,
19110 bool *scroll_step)
19111 {
19112 struct window *w = XWINDOW (window);
19113 struct frame *f = XFRAME (w->frame);
19114 int rc = CURSOR_MOVEMENT_CANNOT_BE_USED;
19115
19116 #ifdef GLYPH_DEBUG
19117 if (inhibit_try_cursor_movement)
19118 return rc;
19119 #endif
19120
19121
19122
19123
19124 eassert (w->last_point > 0);
19125
19126
19127
19128 eassert (!w->window_end_valid
19129 || w->window_end_vpos < w->current_matrix->nrows);
19130
19131
19132
19133 if (
19134 PT >= CHARPOS (startp)
19135
19136 && !current_buffer->clip_changed
19137
19138
19139
19140
19141 && !update_mode_lines
19142 && !windows_or_buffers_changed
19143 && !f->cursor_type_changed
19144 && NILP (Vshow_trailing_whitespace)
19145
19146
19147 && !EQ (Vdisplay_line_numbers, Qrelative)
19148 && !EQ (Vdisplay_line_numbers, Qvisual)
19149
19150
19151
19152 && !(!NILP (Vdisplay_line_numbers)
19153 && NILP (Finternal_lisp_face_equal_p (Qline_number,
19154 Qline_number_current_line,
19155 w->frame)))
19156
19157
19158
19159
19160
19161
19162 && !EQ (window, minibuf_window)
19163
19164
19165
19166 && !overlay_arrow_in_current_buffer_p ())
19167 {
19168 int this_scroll_margin, top_scroll_margin;
19169 struct glyph_row *row = NULL;
19170
19171 #ifdef GLYPH_DEBUG
19172 debug_method_add (w, "cursor movement");
19173 #endif
19174
19175 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
19176
19177 top_scroll_margin = this_scroll_margin;
19178 if (window_wants_tab_line (w))
19179 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
19180 if (window_wants_header_line (w))
19181 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
19182
19183
19184
19185 if (w->last_cursor_vpos < 0
19186 || w->last_cursor_vpos >= w->current_matrix->nrows)
19187 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19188 else
19189 {
19190 row = MATRIX_ROW (w->current_matrix, w->last_cursor_vpos);
19191
19192 if (row->tab_line_p)
19193 ++row;
19194 if (row->mode_line_p)
19195 ++row;
19196 if (!row->enabled_p)
19197 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19198 }
19199
19200 if (rc == CURSOR_MOVEMENT_CANNOT_BE_USED)
19201 {
19202 bool scroll_p = false, must_scroll = false;
19203 int last_y = window_text_bottom_y (w) - this_scroll_margin;
19204
19205 if (PT > w->last_point)
19206 {
19207
19208 while (MATRIX_ROW_END_CHARPOS (row) < PT
19209 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
19210 {
19211 eassert (row->enabled_p);
19212 ++row;
19213 }
19214
19215
19216
19217
19218 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19219 && MATRIX_ROW_END_CHARPOS (row) == PT
19220 && row < MATRIX_MODE_LINE_ROW (w->current_matrix)
19221 && MATRIX_ROW_START_CHARPOS (row+1) >= PT
19222 && !cursor_row_p (row))
19223 ++row;
19224
19225
19226
19227
19228
19229 if (MATRIX_ROW_BOTTOM_Y (row) > last_y
19230 || PT > MATRIX_ROW_END_CHARPOS (row)
19231
19232
19233 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
19234 && PT == MATRIX_ROW_END_CHARPOS (row)
19235 && !row->ends_at_zv_p
19236 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
19237 scroll_p = true;
19238 }
19239 else if (PT < w->last_point)
19240 {
19241
19242
19243 struct glyph_row *row0 = row;
19244
19245 while (!row->mode_line_p
19246 && (MATRIX_ROW_START_CHARPOS (row) > PT
19247 || (MATRIX_ROW_START_CHARPOS (row) == PT
19248 && (MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)
19249 || (
19250 row > w->current_matrix->rows
19251 && (row-1)->ends_in_newline_from_string_p))))
19252 && (row->y > top_scroll_margin
19253 || CHARPOS (startp) == BEGV))
19254 {
19255 eassert (row->enabled_p);
19256 --row;
19257 }
19258
19259
19260
19261
19262
19263 if (!(MATRIX_ROW_START_CHARPOS (row) <= PT
19264 && PT <= MATRIX_ROW_END_CHARPOS (row))
19265 && row0->continued_p)
19266 {
19267 row = row0;
19268 while (MATRIX_ROW_START_CHARPOS (row) > PT
19269 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
19270 {
19271 eassert (row->enabled_p);
19272 ++row;
19273 }
19274 }
19275
19276
19277
19278
19279
19280
19281 if (row < w->current_matrix->rows
19282 || row->mode_line_p)
19283 {
19284 row = w->current_matrix->rows;
19285
19286 if (row->tab_line_p)
19287 ++row;
19288 if (row->mode_line_p)
19289 ++row;
19290 }
19291
19292
19293
19294 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19295 && MATRIX_ROW_END_CHARPOS (row) == PT
19296 && !cursor_row_p (row))
19297 ++row;
19298
19299
19300
19301 if ((row->y < top_scroll_margin
19302 && CHARPOS (startp) != BEGV)
19303 || MATRIX_ROW_BOTTOM_Y (row) > last_y
19304 || PT > MATRIX_ROW_END_CHARPOS (row)
19305 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
19306 && PT == MATRIX_ROW_END_CHARPOS (row)
19307 && !row->ends_at_zv_p
19308 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
19309 scroll_p = true;
19310 }
19311 else
19312 {
19313
19314
19315 rc = CURSOR_MOVEMENT_SUCCESS;
19316 }
19317
19318 if ((PT < MATRIX_ROW_START_CHARPOS (row)
19319 && (row == MATRIX_FIRST_TEXT_ROW (w->current_matrix)
19320
19321
19322 || (MATRIX_ROW_END_CHARPOS (row-1)
19323 == MATRIX_ROW_START_CHARPOS (row))))
19324 || PT > MATRIX_ROW_END_CHARPOS (row))
19325 {
19326
19327 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19328 must_scroll = true;
19329 }
19330 else if (rc != CURSOR_MOVEMENT_SUCCESS
19331 && !NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
19332 {
19333 struct glyph_row *row1;
19334
19335
19336
19337
19338
19339
19340
19341
19342
19343
19344
19345 for (row1 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
19346 MATRIX_ROW_CONTINUATION_LINE_P (row);
19347 --row)
19348 {
19349
19350
19351
19352 if (row <= row1)
19353 {
19354 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19355 break;
19356 }
19357 eassert (row->enabled_p);
19358 }
19359 }
19360 if (must_scroll)
19361 ;
19362 else if (rc != CURSOR_MOVEMENT_SUCCESS
19363 && MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row)
19364
19365
19366
19367 && !row->mode_line_p
19368 && !cursor_row_fully_visible_p (w, true, true, true))
19369 {
19370 if (PT == MATRIX_ROW_END_CHARPOS (row)
19371 && !row->ends_at_zv_p
19372 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
19373 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19374 else if (row->height > window_box_height (w))
19375 {
19376
19377
19378
19379
19380 *scroll_step = true;
19381 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19382 }
19383 else
19384 {
19385 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
19386 if (!cursor_row_fully_visible_p (w, false, true, false))
19387 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19388 else
19389 rc = CURSOR_MOVEMENT_SUCCESS;
19390 }
19391 }
19392 else if (scroll_p)
19393 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19394 else if (rc != CURSOR_MOVEMENT_SUCCESS
19395 && !NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
19396 {
19397
19398
19399
19400
19401
19402
19403
19404 bool rv = false;
19405 bool pt_invis = false;
19406 Lisp_Object val = get_char_property_and_overlay (make_fixnum (PT),
19407 Qinvisible,
19408 Qnil, NULL);
19409
19410 if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
19411 pt_invis = true;
19412
19413 do
19414 {
19415 bool at_zv_p = false, exact_match_p = false;
19416
19417
19418
19419
19420
19421 if ((pt_invis || MATRIX_ROW_START_CHARPOS (row) <= PT)
19422 && PT <= MATRIX_ROW_END_CHARPOS (row)
19423 && cursor_row_p (row))
19424 rv |= set_cursor_from_row (w, row, w->current_matrix,
19425 0, 0, 0, 0);
19426
19427
19428
19429 if (rv)
19430 {
19431 at_zv_p = MATRIX_ROW (w->current_matrix,
19432 w->cursor.vpos)->ends_at_zv_p;
19433 if (!at_zv_p
19434 && w->cursor.hpos >= 0
19435 && w->cursor.hpos < MATRIX_ROW_USED (w->current_matrix,
19436 w->cursor.vpos))
19437 {
19438 struct glyph_row *candidate =
19439 MATRIX_ROW (w->current_matrix, w->cursor.vpos);
19440 struct glyph *g =
19441 candidate->glyphs[TEXT_AREA] + w->cursor.hpos;
19442 ptrdiff_t endpos = MATRIX_ROW_END_CHARPOS (candidate);
19443
19444 exact_match_p =
19445 (BUFFERP (g->object) && g->charpos == PT)
19446 || (NILP (g->object)
19447 && (g->charpos == PT
19448 || (g->charpos == 0 && endpos - 1 == PT)));
19449
19450
19451
19452
19453 if (!exact_match_p && pt_invis)
19454 exact_match_p = true;
19455 }
19456 if (at_zv_p || exact_match_p)
19457 {
19458 rc = CURSOR_MOVEMENT_SUCCESS;
19459 break;
19460 }
19461 }
19462 if (MATRIX_ROW_BOTTOM_Y (row) == last_y)
19463 break;
19464 ++row;
19465 }
19466 while (((MATRIX_ROW_CONTINUATION_LINE_P (row)
19467 || row->continued_p)
19468 && MATRIX_ROW_BOTTOM_Y (row) <= last_y)
19469 || (MATRIX_ROW_START_CHARPOS (row) == PT
19470 && MATRIX_ROW_BOTTOM_Y (row) < last_y));
19471
19472
19473
19474 if (rc != CURSOR_MOVEMENT_SUCCESS
19475 && !(rv
19476 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
19477 && !row->continued_p))
19478 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19479 else if (rv)
19480 rc = CURSOR_MOVEMENT_SUCCESS;
19481 }
19482 else
19483 {
19484 do
19485 {
19486 if (set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0))
19487 {
19488 rc = CURSOR_MOVEMENT_SUCCESS;
19489 break;
19490 }
19491 ++row;
19492 }
19493 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19494 && MATRIX_ROW_START_CHARPOS (row) == PT
19495 && cursor_row_p (row));
19496 }
19497 }
19498 }
19499
19500 return rc;
19501 }
19502
19503
19504 void
19505 set_vertical_scroll_bar (struct window *w)
19506 {
19507 ptrdiff_t start, end, whole;
19508
19509
19510
19511
19512
19513
19514
19515
19516 if (!MINI_WINDOW_P (w)
19517 || (w == XWINDOW (minibuf_window)
19518 && NILP (echo_area_buffer[0])))
19519 {
19520 struct buffer *buf = XBUFFER (w->contents);
19521
19522 whole = BUF_ZV (buf) - BUF_BEGV (buf);
19523 start = marker_position (w->start) - BUF_BEGV (buf);
19524 end = BUF_Z (buf) - w->window_end_pos - BUF_BEGV (buf);
19525
19526
19527
19528
19529 if (!w->window_end_valid && !buf->long_line_optimizations_p)
19530 {
19531 struct it it;
19532 struct text_pos start_pos;
19533 struct buffer *obuf = current_buffer;
19534
19535
19536
19537 set_buffer_internal_1 (XBUFFER (w->contents));
19538 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
19539 start_display (&it, w, start_pos);
19540 move_it_to (&it, -1, it.last_visible_x, window_box_height (w), -1,
19541 MOVE_TO_X | MOVE_TO_Y);
19542 end -= (BUF_Z (buf) - IT_CHARPOS (it)) - w->window_end_pos;
19543 set_buffer_internal_1 (obuf);
19544 }
19545
19546 if (end < start)
19547 end = start;
19548 if (whole < (end - start))
19549 whole = end - start;
19550 }
19551 else
19552 start = end = whole = 0;
19553
19554
19555 if (FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
19556 (*FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
19557 (w, end - start, whole, start);
19558 }
19559
19560
19561 void
19562 set_horizontal_scroll_bar (struct window *w)
19563 {
19564 int start, end, whole, portion;
19565
19566 if (!MINI_WINDOW_P (w) || EQ (w->horizontal_scroll_bar_type, Qbottom))
19567 {
19568 struct buffer *b = XBUFFER (w->contents);
19569 struct buffer *old_buffer = NULL;
19570 struct it it;
19571 struct text_pos startp;
19572
19573 if (b != current_buffer)
19574 {
19575 old_buffer = current_buffer;
19576 set_buffer_internal (b);
19577 }
19578
19579 SET_TEXT_POS_FROM_MARKER (startp, w->start);
19580 start_display (&it, w, startp);
19581 it.last_visible_x = INT_MAX;
19582 whole = move_it_to (&it, -1, INT_MAX, window_box_height (w), -1,
19583 MOVE_TO_X | MOVE_TO_Y);
19584
19585
19586
19587
19588 start = w->hscroll * FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
19589 end = start + window_box_width (w, TEXT_AREA);
19590 portion = end - start;
19591
19592
19593
19594
19595 whole = max (whole, end);
19596
19597 if (it.bidi_p)
19598 {
19599 Lisp_Object pdir;
19600
19601 pdir = Fcurrent_bidi_paragraph_direction (Qnil);
19602 if (EQ (pdir, Qright_to_left))
19603 {
19604 start = whole - end;
19605 end = start + portion;
19606 }
19607 }
19608
19609 if (old_buffer)
19610 set_buffer_internal (old_buffer);
19611 }
19612 else
19613 start = end = whole = portion = 0;
19614
19615 w->hscroll_whole = whole;
19616
19617
19618 if (FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
19619 (*FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
19620 (w, portion, whole, start);
19621 }
19622
19623
19624
19625 static bool
19626 window_start_acceptable_p (Lisp_Object window, ptrdiff_t startp)
19627 {
19628 if (!make_window_start_visible)
19629 return true;
19630
19631 struct window *w = XWINDOW (window);
19632 struct frame *f = XFRAME (w->frame);
19633 Lisp_Object startpos = make_fixnum (startp);
19634 Lisp_Object invprop, disp_spec;
19635 struct text_pos ignored;
19636
19637
19638 if ((invprop = Fget_char_property (startpos, Qinvisible, window)),
19639 TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
19640 return false;
19641
19642
19643 if (!NILP (disp_spec = Fget_char_property (startpos, Qdisplay, window))
19644 && handle_display_spec (NULL, disp_spec, Qnil, Qnil, &ignored, startp,
19645 FRAME_WINDOW_P (f)) > 0)
19646 return false;
19647
19648 return true;
19649 }
19650
19651 DEFUN ("long-line-optimizations-p", Flong_line_optimizations_p, Slong_line_optimizations_p,
19652 0, 0, 0,
19653 doc:
19654
19655 )
19656 (void)
19657 {
19658 return current_buffer->long_line_optimizations_p ? Qt : Qnil;
19659 }
19660
19661
19662
19663
19664
19665
19666
19667
19668
19669
19670
19671
19672
19673
19674
19675
19676
19677
19678
19679
19680
19681
19682
19683
19684
19685
19686
19687
19688
19689
19690
19691
19692
19693
19694
19695
19696
19697
19698
19699
19700
19701
19702
19703
19704
19705
19706
19707
19708
19709
19710
19711 static void
19712 redisplay_window (Lisp_Object window, bool just_this_one_p)
19713 {
19714 struct window *w = XWINDOW (window);
19715 struct frame *f = XFRAME (w->frame);
19716 struct buffer *buffer = XBUFFER (w->contents);
19717 struct buffer *old = current_buffer;
19718 struct text_pos lpoint, opoint, startp;
19719 bool update_mode_line;
19720 int tem;
19721 struct it it;
19722
19723 bool current_matrix_up_to_date_p = false;
19724 bool used_current_matrix_p = false;
19725
19726
19727 bool buffer_unchanged_p = false;
19728 bool temp_scroll_step = false;
19729 specpdl_ref count = SPECPDL_INDEX ();
19730 int rc;
19731 int centering_position = -1;
19732 bool last_line_misfit = false;
19733 ptrdiff_t beg_unchanged, end_unchanged;
19734 int frame_line_height, margin;
19735 bool use_desired_matrix;
19736 void *itdata = NULL;
19737
19738 SET_TEXT_POS (lpoint, PT, PT_BYTE);
19739 opoint = lpoint;
19740
19741 #ifdef GLYPH_DEBUG
19742 *w->desired_matrix->method = 0;
19743 #endif
19744
19745 if (!just_this_one_p && needs_no_redisplay (w))
19746 return;
19747
19748
19749 eassert (XMARKER (w->start)->buffer == buffer);
19750 eassert (XMARKER (w->pointm)->buffer == buffer);
19751
19752 reconsider_clip_changes (w);
19753 frame_line_height = default_line_pixel_height (w);
19754 margin = window_scroll_margin (w, MARGIN_IN_LINES);
19755
19756
19757
19758 update_mode_line = (w->update_mode_line
19759 || update_mode_lines
19760 || buffer->clip_changed
19761 || buffer->prevent_redisplay_optimizations_p);
19762
19763 if (!just_this_one_p)
19764
19765
19766 w->must_be_updated_p = true;
19767
19768 if (MINI_WINDOW_P (w))
19769 {
19770 if (w == XWINDOW (echo_area_window)
19771 && !NILP (echo_area_buffer[0]))
19772 {
19773 if (update_mode_line)
19774
19775
19776 goto finish_menu_bars;
19777 else
19778
19779 goto finish_scroll_bars;
19780 }
19781 else if ((w != XWINDOW (minibuf_window)
19782 || minibuf_level == 0)
19783
19784 && BUF_Z (XBUFFER (w->contents)) == BUF_BEG (XBUFFER (w->contents))
19785
19786
19787 && !NILP (Fmemq (w->contents, Vminibuffer_list)))
19788 {
19789
19790
19791 int yb = window_text_bottom_y (w);
19792 struct glyph_row *row;
19793 int y;
19794
19795 for (y = 0, row = w->desired_matrix->rows;
19796 y < yb;
19797 y += row->height, ++row)
19798 blank_row (w, row, y);
19799 goto finish_scroll_bars;
19800 }
19801 else if (minibuf_level >= 1)
19802 {
19803
19804
19805
19806 resize_mini_window (w, false);
19807 }
19808
19809 clear_glyph_matrix (w->desired_matrix);
19810 }
19811
19812
19813
19814
19815
19816 set_buffer_internal_1 (XBUFFER (w->contents));
19817
19818 current_matrix_up_to_date_p
19819 = (w->window_end_valid
19820 && !current_buffer->clip_changed
19821 && !current_buffer->prevent_redisplay_optimizations_p
19822 && !window_outdated (w)
19823 && !composition_break_at_point
19824 && !hscrolling_current_line_p (w));
19825
19826 beg_unchanged = BEG_UNCHANGED;
19827 end_unchanged = END_UNCHANGED;
19828
19829 SET_TEXT_POS (opoint, PT, PT_BYTE);
19830
19831 specbind (Qinhibit_point_motion_hooks, Qt);
19832
19833 buffer_unchanged_p
19834 = (w->window_end_valid
19835 && !current_buffer->clip_changed
19836 && !window_outdated (w));
19837
19838
19839
19840 if (windows_or_buffers_changed)
19841 {
19842
19843
19844 if (XMARKER (w->start)->buffer == current_buffer)
19845 compute_window_start_on_continuation_line (w);
19846
19847 w->window_end_valid = false;
19848
19849
19850 current_matrix_up_to_date_p = false;
19851 }
19852
19853
19854 CHECK_WINDOW_END (w);
19855 if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
19856 emacs_abort ();
19857 if (BYTEPOS (opoint) < CHARPOS (opoint))
19858 emacs_abort ();
19859
19860 if (mode_line_update_needed (w))
19861 update_mode_line = true;
19862
19863
19864
19865 if (!EQ (window, selected_window))
19866 {
19867 ptrdiff_t new_pt = marker_position (w->pointm);
19868 ptrdiff_t new_pt_byte = marker_byte_position (w->pointm);
19869
19870 if (new_pt < BEGV)
19871 {
19872 new_pt = BEGV;
19873 new_pt_byte = BEGV_BYTE;
19874 set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
19875 }
19876 else if (new_pt > (ZV - 1))
19877 {
19878 new_pt = ZV;
19879 new_pt_byte = ZV_BYTE;
19880 set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
19881 }
19882
19883
19884 TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
19885 }
19886
19887
19888
19889
19890
19891
19892 if (current_buffer->width_run_cache
19893 || (current_buffer->base_buffer
19894 && current_buffer->base_buffer->width_run_cache))
19895 {
19896 struct Lisp_Char_Table *disptab = buffer_display_table ();
19897
19898 if (! disptab_matches_widthtab
19899 (disptab, XVECTOR (BVAR (current_buffer, width_table))))
19900 {
19901 struct buffer *buf = current_buffer;
19902
19903 if (buf->base_buffer)
19904 buf = buf->base_buffer;
19905 invalidate_region_cache (buf, buf->width_run_cache, BEG, Z);
19906 recompute_width_table (current_buffer, disptab);
19907 }
19908 }
19909
19910
19911 if (!NILP (Vlong_line_threshold)
19912 && !current_buffer->long_line_optimizations_p
19913 && (CHARS_MODIFF - UNCHANGED_MODIFIED > 8
19914 || current_buffer->clip_changed))
19915 {
19916 ptrdiff_t cur, next, found, max = 0, threshold;
19917 threshold = XFIXNUM (Vlong_line_threshold);
19918 for (cur = BEGV; cur < ZV; cur = next)
19919 {
19920 next = find_newline1 (cur, CHAR_TO_BYTE (cur), 0, -1, 1,
19921 &found, NULL, true);
19922 if (next - cur > max) max = next - cur;
19923 if (!found || max > threshold) break;
19924 }
19925 if (max > threshold)
19926 current_buffer->long_line_optimizations_p = true;
19927 }
19928
19929
19930 if (XMARKER (w->start)->buffer != current_buffer)
19931 goto recenter;
19932
19933 SET_TEXT_POS_FROM_MARKER (startp, w->start);
19934
19935
19936
19937 if ((w->optional_new_start || window_frozen_p (w))
19938 && CHARPOS (startp) >= BEGV
19939 && CHARPOS (startp) <= ZV)
19940 {
19941 ptrdiff_t it_charpos;
19942
19943 w->optional_new_start = false;
19944 if (!w->force_start)
19945 {
19946 start_display (&it, w, startp);
19947 move_it_to (&it, PT, 0, it.last_visible_y, -1,
19948 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19949
19950
19951 it_charpos = IT_CHARPOS (it);
19952
19953
19954
19955
19956
19957 if (it.current_y == 0 || line_bottom_y (&it) < it.last_visible_y)
19958 {
19959 if (it_charpos == PT)
19960 w->force_start = true;
19961
19962 else if (it_charpos > PT && CHARPOS (startp) <= PT)
19963 w->force_start = true;
19964 #ifdef GLYPH_DEBUG
19965 if (w->force_start)
19966 {
19967 if (window_frozen_p (w))
19968 debug_method_add (w, "set force_start from frozen window start");
19969 else
19970 debug_method_add (w, "set force_start from optional_new_start");
19971 }
19972 #endif
19973 }
19974 }
19975 }
19976
19977 force_start:
19978
19979
19980
19981 if (w->force_start)
19982 {
19983
19984 int new_vpos = -1;
19985
19986 w->force_start = false;
19987
19988
19989
19990
19991 if (!w->preserve_vscroll_p || !window_frozen_p (w))
19992 w->vscroll = 0;
19993
19994 w->preserve_vscroll_p = false;
19995 w->window_end_valid = false;
19996
19997
19998 if (!buffer_unchanged_p)
19999 w->base_line_number = 0;
20000
20001
20002
20003
20004
20005
20006
20007
20008 if (!update_mode_line
20009 || ! NILP (Vwindow_scroll_functions))
20010 {
20011 update_mode_line = true;
20012 w->update_mode_line = true;
20013 startp = run_window_scroll_functions (window, startp);
20014 }
20015
20016 if (CHARPOS (startp) < BEGV)
20017 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
20018 else if (CHARPOS (startp) > ZV)
20019 SET_TEXT_POS (startp, ZV, ZV_BYTE);
20020
20021
20022
20023 if (!window_start_acceptable_p (window, CHARPOS (startp)))
20024 goto ignore_start;
20025
20026
20027
20028
20029
20030
20031 clear_glyph_matrix (w->desired_matrix);
20032 if (!try_window (window, startp, 0))
20033 {
20034 w->force_start = true;
20035 clear_glyph_matrix (w->desired_matrix);
20036 goto need_larger_matrices;
20037 }
20038
20039 if (w->cursor.vpos < 0)
20040 {
20041
20042
20043
20044
20045
20046 struct glyph_row *r = NULL;
20047 Lisp_Object invprop =
20048 get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
20049 Qnil, NULL);
20050
20051 if (TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
20052 {
20053 ptrdiff_t alt_pt;
20054 Lisp_Object invprop_end =
20055 Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
20056 Qnil, Qnil);
20057
20058 if (FIXNATP (invprop_end))
20059 alt_pt = XFIXNAT (invprop_end);
20060 else
20061 alt_pt = ZV;
20062 r = row_containing_pos (w, alt_pt, w->desired_matrix->rows,
20063 NULL, 0);
20064 }
20065 if (r)
20066 new_vpos = MATRIX_ROW_BOTTOM_Y (r);
20067 else
20068 new_vpos = window_box_height (w) / 2;
20069 }
20070
20071 if (!cursor_row_fully_visible_p (w, false, false, false))
20072 {
20073
20074
20075 new_vpos = window_box_height (w);
20076
20077
20078
20079
20080
20081
20082 if (new_vpos >= w->cursor.y)
20083 {
20084 w->cursor.vpos = -1;
20085 clear_glyph_matrix (w->desired_matrix);
20086 goto try_to_scroll;
20087 }
20088 }
20089 else if (w->cursor.vpos >= 0)
20090 {
20091
20092
20093
20094 int pixel_margin = margin * frame_line_height;
20095 bool tab_line = window_wants_tab_line (w);
20096 bool header_line = window_wants_header_line (w);
20097
20098
20099
20100
20101
20102 if (w->cursor.vpos < margin + tab_line + header_line)
20103 {
20104 w->cursor.vpos = -1;
20105 clear_glyph_matrix (w->desired_matrix);
20106 goto try_to_scroll;
20107 }
20108 else
20109 {
20110 int window_height = window_box_height (w);
20111
20112 if (tab_line)
20113 window_height += CURRENT_TAB_LINE_HEIGHT (w);
20114 if (header_line)
20115 window_height += CURRENT_HEADER_LINE_HEIGHT (w);
20116 if (w->cursor.y >= window_height - pixel_margin)
20117 {
20118 w->cursor.vpos = -1;
20119 clear_glyph_matrix (w->desired_matrix);
20120 goto try_to_scroll;
20121 }
20122 }
20123 }
20124
20125
20126
20127 if (new_vpos >= 0)
20128 {
20129 struct glyph_row *row;
20130
20131 row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix);
20132 while (MATRIX_ROW_BOTTOM_Y (row) < new_vpos
20133 && !row->ends_at_zv_p)
20134 ++row;
20135
20136 TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
20137 MATRIX_ROW_START_BYTEPOS (row));
20138
20139 if (w != XWINDOW (selected_window))
20140 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
20141 else if (current_buffer == old)
20142 SET_TEXT_POS (lpoint, PT, PT_BYTE);
20143
20144 set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
20145
20146
20147
20148
20149
20150
20151
20152 w->redisplay = false;
20153 XBUFFER (w->contents)->text->redisplay = false;
20154 safe__call1 (true, Vpre_redisplay_function, Fcons (window, Qnil));
20155
20156 if (w->redisplay || XBUFFER (w->contents)->text->redisplay
20157 || ((EQ (Vdisplay_line_numbers, Qrelative)
20158 || EQ (Vdisplay_line_numbers, Qvisual))
20159 && row != MATRIX_FIRST_TEXT_ROW (w->desired_matrix)))
20160 {
20161
20162
20163
20164
20165 clear_glyph_matrix (w->desired_matrix);
20166 if (!try_window (window, startp, 0))
20167 goto need_larger_matrices;
20168 }
20169 }
20170 if (w->cursor.vpos < 0
20171 || !cursor_row_fully_visible_p (w, false, false, false))
20172 {
20173 clear_glyph_matrix (w->desired_matrix);
20174 goto try_to_scroll;
20175 }
20176
20177 #ifdef GLYPH_DEBUG
20178 debug_method_add (w, "forced window start");
20179 #endif
20180 goto done;
20181 }
20182
20183 ignore_start:
20184
20185
20186
20187
20188 if (current_matrix_up_to_date_p
20189 && (rc = try_cursor_movement (window, startp, &temp_scroll_step),
20190 rc != CURSOR_MOVEMENT_CANNOT_BE_USED))
20191 {
20192 switch (rc)
20193 {
20194 case CURSOR_MOVEMENT_SUCCESS:
20195 used_current_matrix_p = true;
20196 goto done;
20197
20198 case CURSOR_MOVEMENT_MUST_SCROLL:
20199 goto try_to_scroll;
20200
20201 default:
20202 emacs_abort ();
20203 }
20204 }
20205
20206
20207
20208 else if (w->start_at_line_beg
20209 && ((CHARPOS (startp) > BEGV
20210 && FETCH_BYTE (BYTEPOS (startp) - 1) != '\n')
20211 || (CHARPOS (startp) >= BEGV
20212 && CHARPOS (startp) <= ZV
20213 && !window_start_acceptable_p (window, CHARPOS (startp)))))
20214 {
20215 #ifdef GLYPH_DEBUG
20216 debug_method_add (w, "recenter 1");
20217 #endif
20218 goto recenter;
20219 }
20220
20221
20222
20223
20224 else if ((tem = try_window_id (w)) != 0)
20225 {
20226 #ifdef GLYPH_DEBUG
20227 debug_method_add (w, "try_window_id %d", tem);
20228 #endif
20229
20230 if (f->fonts_changed)
20231 goto need_larger_matrices;
20232 if (tem > 0)
20233 goto done;
20234
20235
20236
20237 }
20238 else if (CHARPOS (startp) >= BEGV
20239 && CHARPOS (startp) <= ZV
20240 && PT >= CHARPOS (startp)
20241 && (CHARPOS (startp) < ZV
20242
20243 || CHARPOS (startp) == BEGV
20244 || !window_outdated (w)))
20245 {
20246 int d1, d2, d5, d6;
20247 int rtop, rbot;
20248
20249
20250
20251
20252
20253
20254
20255
20256
20257
20258 if (!w->start_at_line_beg
20259 && NILP (track_mouse)
20260 && CHARPOS (startp) > BEGV
20261 && CHARPOS (startp) > BEG + beg_unchanged
20262 && CHARPOS (startp) <= Z - end_unchanged
20263
20264
20265
20266
20267
20268 && XMARKER (w->start)->buffer == current_buffer
20269 && compute_window_start_on_continuation_line (w)
20270
20271
20272
20273
20274
20275
20276 && pos_visible_p (w, PT, &d1, &d2, &rtop, &rbot, &d5, &d6)
20277
20278
20279 && (rtop != 0) == (rbot != 0))
20280 {
20281 w->force_start = true;
20282 SET_TEXT_POS_FROM_MARKER (startp, w->start);
20283 #ifdef GLYPH_DEBUG
20284 debug_method_add (w, "recomputed window start in continuation line");
20285 #endif
20286 goto force_start;
20287 }
20288
20289
20290
20291
20292 if (!window_start_acceptable_p (window, CHARPOS (startp)))
20293 {
20294 #ifdef GLYPH_DEBUG
20295 debug_method_add (w, "recenter 2");
20296 #endif
20297 goto recenter;
20298 }
20299
20300 #ifdef GLYPH_DEBUG
20301 debug_method_add (w, "same window start");
20302 #endif
20303
20304
20305
20306 if (!current_matrix_up_to_date_p
20307
20308
20309
20310 || !NILP (Vwindow_scroll_functions)
20311 || MINI_WINDOW_P (w)
20312 || !(used_current_matrix_p
20313 = try_window_reusing_current_matrix (w)))
20314 {
20315 IF_DEBUG (debug_method_add (w, "1"));
20316 clear_glyph_matrix (w->desired_matrix);
20317 if (try_window (window, startp, TRY_WINDOW_CHECK_MARGINS) < 0)
20318
20319
20320
20321 goto try_to_scroll;
20322 }
20323
20324 if (f->fonts_changed)
20325 goto need_larger_matrices;
20326
20327 if (w->cursor.vpos >= 0)
20328 {
20329 if (!just_this_one_p
20330 || current_buffer->clip_changed
20331 || BEG_UNCHANGED < CHARPOS (startp))
20332
20333 w->base_line_number = 0;
20334
20335 if (!cursor_row_fully_visible_p (w, true, false, false))
20336 {
20337 clear_glyph_matrix (w->desired_matrix);
20338 last_line_misfit = true;
20339 }
20340
20341 else
20342 goto done;
20343 }
20344 else
20345 clear_glyph_matrix (w->desired_matrix);
20346 }
20347
20348 try_to_scroll:
20349
20350
20351 if (!update_mode_line)
20352 {
20353 update_mode_line = true;
20354 w->update_mode_line = true;
20355 }
20356
20357
20358 if ((0 < scroll_conservatively
20359
20360
20361
20362
20363 || (scroll_minibuffer_conservatively && MINI_WINDOW_P (w))
20364 || 0 < emacs_scroll_step
20365 || temp_scroll_step
20366 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively))
20367 || NUMBERP (BVAR (current_buffer, scroll_down_aggressively)))
20368 && CHARPOS (startp) >= BEGV
20369 && CHARPOS (startp) <= ZV)
20370 {
20371
20372
20373 int ss = try_scrolling (window, just_this_one_p,
20374 ((scroll_minibuffer_conservatively
20375 && MINI_WINDOW_P (w))
20376 ? SCROLL_LIMIT + 1
20377 : scroll_conservatively),
20378 emacs_scroll_step,
20379 temp_scroll_step, last_line_misfit);
20380 switch (ss)
20381 {
20382 case SCROLLING_SUCCESS:
20383 goto done;
20384
20385 case SCROLLING_NEED_LARGER_MATRICES:
20386 goto need_larger_matrices;
20387
20388 case SCROLLING_FAILED:
20389 break;
20390
20391 default:
20392 emacs_abort ();
20393 }
20394 }
20395
20396
20397
20398
20399 recenter:
20400
20401 #ifdef GLYPH_DEBUG
20402 debug_method_add (w, "recenter");
20403 #endif
20404
20405
20406 if (!buffer_unchanged_p)
20407 w->base_line_number = 0;
20408
20409
20410 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
20411 it.current_y = it.last_visible_y;
20412 if (centering_position < 0)
20413 {
20414 ptrdiff_t margin_pos = CHARPOS (startp);
20415 Lisp_Object aggressive;
20416 bool scrolling_up;
20417
20418
20419
20420 if (margin
20421
20422
20423
20424
20425
20426
20427 && BEGV <= CHARPOS (startp) && CHARPOS (startp) <= ZV)
20428 {
20429 struct it it1;
20430 void *it1data = NULL;
20431
20432 SAVE_IT (it1, it, it1data);
20433 start_display (&it1, w, startp);
20434 move_it_vertically (&it1, margin * frame_line_height);
20435 margin_pos = IT_CHARPOS (it1);
20436 RESTORE_IT (&it, &it, it1data);
20437 }
20438 scrolling_up = PT > margin_pos;
20439 aggressive =
20440 scrolling_up
20441 ? BVAR (current_buffer, scroll_up_aggressively)
20442 : BVAR (current_buffer, scroll_down_aggressively);
20443
20444 if (!MINI_WINDOW_P (w)
20445 && (scroll_conservatively > SCROLL_LIMIT || NUMBERP (aggressive)))
20446 {
20447 int pt_offset = 0;
20448
20449
20450
20451 if (!scroll_conservatively && NUMBERP (aggressive))
20452 {
20453 double float_amount = XFLOATINT (aggressive);
20454
20455 pt_offset = float_amount * WINDOW_BOX_TEXT_HEIGHT (w);
20456 if (pt_offset == 0 && float_amount > 0)
20457 pt_offset = 1;
20458 if (pt_offset && margin > 0)
20459 margin -= 1;
20460 }
20461
20462
20463
20464 if (scrolling_up)
20465 {
20466 centering_position = it.last_visible_y;
20467 if (pt_offset)
20468 centering_position -= pt_offset;
20469 centering_position -=
20470 (frame_line_height * (1 + margin + last_line_misfit)
20471 + WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w));
20472
20473
20474 if (centering_position < margin * frame_line_height)
20475 centering_position = margin * frame_line_height;
20476 }
20477 else
20478 centering_position = margin * frame_line_height + pt_offset;
20479 }
20480 else
20481
20482
20483 centering_position = window_box_height (w) / 2;
20484 }
20485 if (current_buffer->long_line_optimizations_p
20486 && it.line_wrap == TRUNCATE)
20487 {
20488
20489
20490
20491 int nlines = centering_position / frame_line_height;
20492
20493 while (nlines-- && IT_CHARPOS (it) > BEGV)
20494 back_to_previous_visible_line_start (&it);
20495 reseat_1 (&it, it.current.pos, true);
20496 }
20497 else
20498 move_it_vertically_backward (&it, centering_position);
20499
20500 eassert (IT_CHARPOS (it) >= BEGV);
20501
20502
20503
20504
20505
20506
20507 if (it.current_y <= 0)
20508 {
20509 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
20510 move_it_vertically_backward (&it, 0);
20511 it.current_y = 0;
20512 }
20513
20514 it.current_x = it.hpos = 0;
20515
20516
20517
20518
20519 set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
20520
20521
20522 startp = run_window_scroll_functions (window, it.current.pos);
20523
20524
20525
20526
20527 itdata = bidi_shelve_cache ();
20528
20529
20530 use_desired_matrix = false;
20531 if (!current_matrix_up_to_date_p
20532 || windows_or_buffers_changed
20533 || f->cursor_type_changed
20534
20535
20536 || !NILP (Vwindow_scroll_functions)
20537 || !just_this_one_p
20538 || MINI_WINDOW_P (w)
20539 || !(used_current_matrix_p
20540 = try_window_reusing_current_matrix (w)))
20541 use_desired_matrix = (try_window (window, startp, 0) == 1);
20542
20543 bidi_unshelve_cache (itdata, false);
20544
20545
20546
20547
20548 if (f->fonts_changed)
20549 goto need_larger_matrices;
20550
20551
20552
20553
20554
20555
20556 if (w->cursor.vpos < 0)
20557 {
20558 if (w->window_end_valid && PT >= Z - w->window_end_pos)
20559 {
20560 clear_glyph_matrix (w->desired_matrix);
20561 move_it_by_lines (&it, 1);
20562 try_window (window, it.current.pos, 0);
20563 }
20564 else if (PT < IT_CHARPOS (it))
20565 {
20566 clear_glyph_matrix (w->desired_matrix);
20567 move_it_by_lines (&it, -1);
20568 try_window (window, it.current.pos, 0);
20569 }
20570 else if (scroll_conservatively > SCROLL_LIMIT
20571 && (it.method == GET_FROM_STRING
20572 || overlay_touches_p (IT_CHARPOS (it)))
20573 && IT_CHARPOS (it) < ZV)
20574 {
20575
20576
20577
20578
20579
20580
20581
20582
20583 ptrdiff_t pos0 = IT_CHARPOS (it);
20584
20585 clear_glyph_matrix (w->desired_matrix);
20586 do {
20587 move_it_by_lines (&it, 1);
20588 } while (IT_CHARPOS (it) == pos0);
20589 try_window (window, it.current.pos, 0);
20590 }
20591 else
20592 {
20593
20594 }
20595 }
20596
20597
20598
20599
20600
20601
20602 if (w->cursor.vpos < 0)
20603 {
20604
20605
20606
20607
20608 struct glyph_matrix *matrix =
20609 use_desired_matrix ? w->desired_matrix : w->current_matrix;
20610
20611 struct glyph_row *row =
20612 row_containing_pos (w, PT, matrix->rows, NULL, 0);
20613
20614
20615
20616
20617
20618
20619
20620 if (!row)
20621 {
20622 Lisp_Object val =
20623 get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
20624 Qnil, NULL);
20625
20626 if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
20627 {
20628 ptrdiff_t alt_pos;
20629 Lisp_Object invis_end =
20630 Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
20631 Qnil, Qnil);
20632
20633 if (FIXNATP (invis_end))
20634 alt_pos = XFIXNAT (invis_end);
20635 else
20636 alt_pos = ZV;
20637 row = row_containing_pos (w, alt_pos, matrix->rows, NULL, 0);
20638 }
20639 }
20640
20641
20642
20643 if (!row)
20644 {
20645 row = matrix->rows;
20646
20647 if (row->tab_line_p)
20648 ++row;
20649 if (row->mode_line_p)
20650 ++row;
20651 }
20652 set_cursor_from_row (w, row, matrix, 0, 0, 0, 0);
20653 }
20654
20655 if (!cursor_row_fully_visible_p (w, false, false, false))
20656 {
20657
20658 if (w->vscroll)
20659 {
20660 w->vscroll = 0;
20661 clear_glyph_matrix (w->desired_matrix);
20662 goto recenter;
20663 }
20664
20665
20666
20667
20668
20669 if (scroll_conservatively > SCROLL_LIMIT)
20670 {
20671 int window_total_lines
20672 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
20673 bool move_down = w->cursor.vpos >= window_total_lines / 2;
20674
20675 move_it_by_lines (&it, move_down ? margin + 1 : -(margin + 1));
20676 clear_glyph_matrix (w->desired_matrix);
20677 if (1 == try_window (window, it.current.pos,
20678 TRY_WINDOW_CHECK_MARGINS))
20679 goto done;
20680 }
20681
20682
20683
20684
20685 if (centering_position == 0)
20686 goto done;
20687
20688 clear_glyph_matrix (w->desired_matrix);
20689 centering_position = 0;
20690 goto recenter;
20691 }
20692
20693 done:
20694
20695 SET_TEXT_POS_FROM_MARKER (startp, w->start);
20696 w->start_at_line_beg = (CHARPOS (startp) == BEGV
20697 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n');
20698
20699
20700 if ((update_mode_line
20701
20702
20703
20704
20705 || (!just_this_one_p
20706 && !FRAME_WINDOW_P (f)
20707 && !WINDOW_FULL_WIDTH_P (w))
20708
20709 || w->base_line_pos > 0
20710
20711 || (w->column_number_displayed != -1
20712 && (w->column_number_displayed != current_column ())))
20713
20714 && (window_wants_mode_line (w)
20715 || window_wants_header_line (w)
20716 || window_wants_tab_line (w)))
20717 {
20718 specpdl_ref count1 = SPECPDL_INDEX ();
20719
20720 specbind (Qinhibit_quit, Qt);
20721 display_mode_lines (w);
20722 unbind_to (count1, Qnil);
20723
20724
20725
20726 if (window_wants_mode_line (w)
20727 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
20728 {
20729 f->fonts_changed = true;
20730 w->mode_line_height = -1;
20731 MATRIX_MODE_LINE_ROW (w->current_matrix)->height
20732 = DESIRED_MODE_LINE_HEIGHT (w);
20733 }
20734
20735
20736
20737 if (window_wants_tab_line (w)
20738 && CURRENT_TAB_LINE_HEIGHT (w) != DESIRED_TAB_LINE_HEIGHT (w))
20739 {
20740 f->fonts_changed = true;
20741 w->tab_line_height = -1;
20742 MATRIX_TAB_LINE_ROW (w->current_matrix)->height
20743 = DESIRED_TAB_LINE_HEIGHT (w);
20744 }
20745
20746
20747
20748 if (window_wants_header_line (w)
20749 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
20750 {
20751 f->fonts_changed = true;
20752 w->header_line_height = -1;
20753 MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
20754 = DESIRED_HEADER_LINE_HEIGHT (w);
20755 }
20756
20757 if (f->fonts_changed)
20758 goto need_larger_matrices;
20759 }
20760
20761 if (!line_number_displayed && w->base_line_pos != -1)
20762 {
20763 w->base_line_pos = 0;
20764 w->base_line_number = 0;
20765 }
20766
20767 finish_menu_bars:
20768
20769
20770
20771 if (update_mode_line
20772 && EQ (FRAME_SELECTED_WINDOW (f), window))
20773 {
20774 bool redisplay_menu_p;
20775
20776 if (FRAME_WINDOW_P (f))
20777 {
20778 #ifdef HAVE_EXT_MENU_BAR
20779 redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
20780 #else
20781 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
20782 #endif
20783 }
20784 else
20785 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
20786
20787 if (redisplay_menu_p)
20788 display_menu_bar (w);
20789
20790 #ifdef HAVE_WINDOW_SYSTEM
20791 if (FRAME_WINDOW_P (f))
20792 {
20793 if (WINDOWP (f->tab_bar_window)
20794 && (FRAME_TAB_BAR_LINES (f) > 0
20795 || !NILP (Vauto_resize_tab_bars))
20796 && redisplay_tab_bar (f))
20797 ignore_mouse_drag_p = true;
20798
20799 #ifdef HAVE_EXT_TOOL_BAR
20800 if (FRAME_EXTERNAL_TOOL_BAR (f))
20801 update_frame_tool_bar (f);
20802 #else
20803 if (WINDOWP (f->tool_bar_window)
20804 && (FRAME_TOOL_BAR_LINES (f) > 0
20805 || !NILP (Vauto_resize_tool_bars))
20806 && redisplay_tool_bar (f))
20807 ignore_mouse_drag_p = true;
20808 #endif
20809 }
20810 else
20811 {
20812 if ((FRAME_TAB_BAR_LINES (f) > 0))
20813 display_tab_bar (w);
20814 }
20815
20816 gui_consider_frame_title (w->frame);
20817 #else
20818 if ((FRAME_TAB_BAR_LINES (f) > 0))
20819 display_tab_bar (w);
20820 #endif
20821 }
20822
20823 #ifdef HAVE_WINDOW_SYSTEM
20824 if (FRAME_WINDOW_P (f)
20825 && update_window_fringes (w, (just_this_one_p
20826 || (!used_current_matrix_p && !overlay_arrow_seen)
20827 || w->pseudo_window_p)))
20828 {
20829 update_begin (f);
20830 block_input ();
20831 if (draw_window_fringes (w, true))
20832 {
20833 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
20834 gui_draw_right_divider (w);
20835 else
20836 gui_draw_vertical_border (w);
20837 }
20838 unblock_input ();
20839 update_end (f);
20840 }
20841
20842 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
20843 gui_draw_bottom_divider (w);
20844 #endif
20845
20846
20847
20848
20849
20850 need_larger_matrices:
20851 ;
20852 finish_scroll_bars:
20853
20854 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w) || WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
20855 {
20856 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
20857
20858 set_vertical_scroll_bar (w);
20859
20860 if (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
20861
20862 set_horizontal_scroll_bar (w);
20863
20864
20865
20866 if (FRAME_TERMINAL (f)->redeem_scroll_bar_hook)
20867 (*FRAME_TERMINAL (f)->redeem_scroll_bar_hook) (w);
20868 }
20869
20870
20871
20872
20873 if (CHARPOS (opoint) < BEGV)
20874 TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
20875 else if (CHARPOS (opoint) > ZV)
20876 TEMP_SET_PT_BOTH (Z, Z_BYTE);
20877 else
20878 TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
20879
20880 set_buffer_internal_1 (old);
20881
20882
20883 if (CHARPOS (lpoint) <= ZV)
20884 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
20885
20886 unbind_to (count, Qnil);
20887 }
20888
20889
20890
20891
20892
20893
20894
20895
20896
20897
20898
20899
20900
20901
20902
20903
20904
20905
20906
20907
20908 int
20909 try_window (Lisp_Object window, struct text_pos pos, int flags)
20910 {
20911 struct window *w = XWINDOW (window);
20912 struct it it;
20913 struct glyph_row *last_text_row = NULL;
20914 struct frame *f = XFRAME (w->frame);
20915 int cursor_vpos = w->cursor.vpos;
20916
20917
20918 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
20919
20920
20921 w->cursor.vpos = -1;
20922 overlay_arrow_seen = false;
20923
20924
20925 start_display (&it, w, pos);
20926 it.glyph_row->reversed_p = false;
20927
20928
20929 while (it.current_y < it.last_visible_y)
20930 {
20931 int last_row_scale = it.w->nrows_scale_factor;
20932 int last_col_scale = it.w->ncols_scale_factor;
20933 if (display_line (&it, cursor_vpos))
20934 last_text_row = it.glyph_row - 1;
20935 if (f->fonts_changed
20936 && !((flags & TRY_WINDOW_IGNORE_FONTS_CHANGE)
20937
20938
20939 && last_row_scale == it.w->nrows_scale_factor
20940 && last_col_scale == it.w->ncols_scale_factor))
20941 return 0;
20942 }
20943
20944
20945
20946 ptrdiff_t it_charpos = IT_CHARPOS (it);
20947
20948
20949
20950
20951 if ((flags & TRY_WINDOW_CHECK_MARGINS)
20952 && w->vscroll == 0
20953 && !MINI_WINDOW_P (w))
20954 {
20955 int top_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
20956 int bot_scroll_margin = top_scroll_margin;
20957 if (window_wants_header_line (w))
20958 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
20959 if (window_wants_tab_line (w))
20960 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
20961 start_display (&it, w, pos);
20962
20963 if ((w->cursor.y >= 0
20964 && w->cursor.y < top_scroll_margin
20965 && CHARPOS (pos) > BEGV)
20966
20967
20968
20969
20970 || w->cursor.y > (it.last_visible_y - partial_line_height (&it)
20971 - bot_scroll_margin - 1))
20972 {
20973 w->cursor.vpos = -1;
20974 clear_glyph_matrix (w->desired_matrix);
20975 return -1;
20976 }
20977 }
20978
20979
20980 if (w->window_end_pos <= 0 && Z != it_charpos)
20981 w->update_mode_line = true;
20982
20983
20984
20985
20986 if (last_text_row)
20987 {
20988 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
20989 adjust_window_ends (w, last_text_row, false);
20990 eassert
20991 (MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->desired_matrix,
20992 w->window_end_vpos)));
20993 }
20994 else
20995 {
20996 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
20997 w->window_end_pos = Z - ZV;
20998 w->window_end_vpos = 0;
20999 }
21000
21001
21002 w->window_end_valid = false;
21003 return 1;
21004 }
21005
21006
21007
21008
21009
21010
21011
21012
21013
21014
21015
21016
21017 static bool
21018 try_window_reusing_current_matrix (struct window *w)
21019 {
21020 struct frame *f = XFRAME (w->frame);
21021 struct glyph_row *bottom_row;
21022 struct it it;
21023 struct run run;
21024 struct text_pos start, new_start;
21025 int nrows_scrolled, i;
21026 struct glyph_row *last_text_row;
21027 struct glyph_row *last_reused_text_row;
21028 struct glyph_row *start_row;
21029 int start_vpos, min_y, max_y;
21030
21031 #ifdef GLYPH_DEBUG
21032 if (inhibit_try_window_reusing)
21033 return false;
21034 #endif
21035
21036 if (
21037 !FRAME_WINDOW_P (f)
21038
21039
21040 || windows_or_buffers_changed
21041 || f->cursor_type_changed
21042
21043
21044
21045 || overlay_arrow_in_current_buffer_p ())
21046 return false;
21047
21048
21049 if (!NILP (Vshow_trailing_whitespace))
21050 return false;
21051
21052
21053 if (window_wants_tab_line (w)
21054 != MATRIX_TAB_LINE_ROW (w->current_matrix)->mode_line_p)
21055 return false;
21056
21057
21058 if (window_wants_header_line (w)
21059 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p)
21060 return false;
21061
21062
21063
21064 start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21065 if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row))
21066 return false;
21067
21068
21069 clear_glyph_matrix (w->desired_matrix);
21070
21071
21072
21073
21074 if (!NILP (Vdisplay_line_numbers))
21075 return false;
21076
21077
21078
21079
21080 #ifdef HAVE_NTGUI
21081 if (w32_use_visible_system_caret)
21082 return false;
21083 #endif
21084
21085
21086
21087 SET_TEXT_POS_FROM_MARKER (new_start, w->start);
21088 start = start_row->minpos;
21089 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
21090
21091 if (CHARPOS (new_start) <= CHARPOS (start))
21092 {
21093
21094
21095
21096
21097 if (in_ellipses_for_invisible_text_p (&start_row->start, w))
21098 return false;
21099
21100 IF_DEBUG (debug_method_add (w, "twu1"));
21101
21102
21103
21104
21105
21106 start_display (&it, w, new_start);
21107 w->cursor.vpos = -1;
21108 last_text_row = last_reused_text_row = NULL;
21109
21110 while (it.current_y < it.last_visible_y && !f->fonts_changed)
21111 {
21112
21113
21114
21115
21116 while (IT_CHARPOS (it) > CHARPOS (start))
21117 {
21118
21119 start_row++;
21120 start = start_row->minpos;
21121
21122 if (start_row == MATRIX_MODE_LINE_ROW (w->current_matrix) - 1
21123 || w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row)
21124 || CHARPOS (start) == ZV)
21125 {
21126 clear_glyph_matrix (w->desired_matrix);
21127 return false;
21128 }
21129
21130 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
21131 }
21132
21133
21134 if (IT_CHARPOS (it) == CHARPOS (start)
21135
21136
21137
21138
21139
21140 && it.current.dpvec_index < 0)
21141 break;
21142
21143 it.glyph_row->reversed_p = false;
21144 if (display_line (&it, -1))
21145 last_text_row = it.glyph_row - 1;
21146
21147 }
21148
21149
21150
21151
21152 if (it.current_y < it.last_visible_y)
21153 {
21154 struct glyph_row *row;
21155
21156
21157 nrows_scrolled = it.vpos - (start_row - MATRIX_FIRST_TEXT_ROW (w->current_matrix));
21158
21159
21160 if (w->cursor.vpos < 0)
21161 {
21162 int dy = it.current_y - start_row->y;
21163
21164 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21165 row = row_containing_pos (w, PT, row, NULL, dy);
21166 if (row)
21167 set_cursor_from_row (w, row, w->current_matrix, 0, 0,
21168 dy, nrows_scrolled);
21169 else
21170 {
21171 clear_glyph_matrix (w->desired_matrix);
21172 return false;
21173 }
21174 }
21175
21176
21177
21178
21179
21180
21181
21182 run.current_y = start_row->y;
21183 run.desired_y = it.current_y;
21184 run.height = it.last_visible_y - it.current_y;
21185
21186 if (run.height > 0 && run.current_y != run.desired_y)
21187 {
21188 #ifdef HAVE_WINDOW_SYSTEM
21189 update_begin (f);
21190 gui_update_window_begin (w);
21191 FRAME_RIF (f)->clear_window_mouse_face (w);
21192 FRAME_RIF (f)->scroll_run_hook (w, &run);
21193 gui_update_window_end (w, false, false);
21194 update_end (f);
21195 #endif
21196 }
21197
21198
21199 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
21200 rotate_matrix (w->current_matrix,
21201 start_vpos,
21202 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
21203 nrows_scrolled);
21204
21205
21206 for (i = 0; i < nrows_scrolled; ++i)
21207 (start_row + i)->enabled_p = false;
21208
21209
21210 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21211 max_y = it.last_visible_y;
21212 for (row = start_row + nrows_scrolled;
21213 row < bottom_row;
21214 ++row)
21215 {
21216 row->y = it.current_y;
21217 row->visible_height = row->height;
21218
21219 if (row->y < min_y)
21220 row->visible_height -= min_y - row->y;
21221 if (row->y + row->height > max_y)
21222 row->visible_height -= row->y + row->height - max_y;
21223 if (row->fringe_bitmap_periodic_p)
21224 row->redraw_fringe_bitmaps_p = true;
21225
21226 it.current_y += row->height;
21227
21228 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21229 last_reused_text_row = row;
21230 if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y)
21231 break;
21232 }
21233
21234
21235
21236 for (++row; row < bottom_row; ++row)
21237 row->enabled_p = row->mode_line_p = row->tab_line_p = false;
21238 }
21239
21240
21241
21242
21243
21244 if (last_reused_text_row)
21245 adjust_window_ends (w, last_reused_text_row, true);
21246 else if (last_text_row)
21247 adjust_window_ends (w, last_text_row, false);
21248 else
21249 {
21250
21251 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
21252 w->window_end_pos = Z - ZV;
21253 w->window_end_vpos = 0;
21254 }
21255 w->window_end_valid = false;
21256
21257
21258 w->desired_matrix->no_scrolling_p = true;
21259
21260 #ifdef GLYPH_DEBUG
21261 debug_method_add (w, "try_window_reusing_current_matrix 1");
21262 #endif
21263 return true;
21264 }
21265 else if (CHARPOS (new_start) > CHARPOS (start))
21266 {
21267 struct glyph_row *pt_row, *row;
21268 struct glyph_row *first_reusable_row;
21269 struct glyph_row *first_row_to_display;
21270 int dy;
21271 int yb = window_text_bottom_y (w);
21272
21273
21274
21275 first_reusable_row = start_row;
21276 while (first_reusable_row->enabled_p
21277 && MATRIX_ROW_BOTTOM_Y (first_reusable_row) < yb
21278 && (MATRIX_ROW_START_CHARPOS (first_reusable_row)
21279 < CHARPOS (new_start)))
21280 ++first_reusable_row;
21281
21282
21283 if (MATRIX_ROW_BOTTOM_Y (first_reusable_row) >= yb
21284 || !first_reusable_row->enabled_p
21285 || (MATRIX_ROW_START_CHARPOS (first_reusable_row)
21286 != CHARPOS (new_start)))
21287 return false;
21288
21289
21290
21291
21292
21293 pt_row = NULL;
21294 for (first_row_to_display = first_reusable_row;
21295 MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb;
21296 ++first_row_to_display)
21297 {
21298 if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
21299 && (PT < MATRIX_ROW_END_CHARPOS (first_row_to_display)
21300 || (PT == MATRIX_ROW_END_CHARPOS (first_row_to_display)
21301 && first_row_to_display->ends_at_zv_p
21302 && pt_row == NULL)))
21303 pt_row = first_row_to_display;
21304 }
21305
21306 if (first_row_to_display->y >= yb)
21307 return false;
21308
21309
21310 init_to_row_start (&it, w, first_row_to_display);
21311
21312 nrows_scrolled = (MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix)
21313 - start_vpos);
21314 it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
21315 - nrows_scrolled);
21316 it.current_y = (first_row_to_display->y - first_reusable_row->y
21317 + WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w));
21318
21319
21320
21321
21322 it.glyph_row = MATRIX_ROW (w->desired_matrix, it.vpos);
21323 if (pt_row == NULL)
21324 w->cursor.vpos = -1;
21325 last_text_row = NULL;
21326 while (it.current_y < it.last_visible_y && !f->fonts_changed)
21327 if (display_line (&it, w->cursor.vpos))
21328 last_text_row = it.glyph_row - 1;
21329
21330
21331
21332 if (pt_row)
21333 {
21334 w->cursor.vpos -= nrows_scrolled;
21335 w->cursor.y -= first_reusable_row->y - start_row->y;
21336 }
21337
21338
21339
21340
21341
21342 if (w->cursor.vpos < 0)
21343 {
21344 clear_glyph_matrix (w->desired_matrix);
21345 return false;
21346 }
21347
21348
21349 run.current_y = first_reusable_row->y;
21350 run.desired_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21351 run.height = it.last_visible_y - run.current_y;
21352 dy = run.current_y - run.desired_y;
21353
21354 if (run.height)
21355 {
21356 #ifdef HAVE_WINDOW_SYSTEM
21357 update_begin (f);
21358 gui_update_window_begin (w);
21359 FRAME_RIF (f)->clear_window_mouse_face (w);
21360 FRAME_RIF (f)->scroll_run_hook (w, &run);
21361 gui_update_window_end (w, false, false);
21362 update_end (f);
21363 #endif
21364 }
21365
21366
21367 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
21368 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21369 max_y = it.last_visible_y;
21370 for (row = first_reusable_row; row < first_row_to_display; ++row)
21371 {
21372 row->y -= dy;
21373 row->visible_height = row->height;
21374 if (row->y < min_y)
21375 row->visible_height -= min_y - row->y;
21376 if (row->y + row->height > max_y)
21377 row->visible_height -= row->y + row->height - max_y;
21378 if (row->fringe_bitmap_periodic_p)
21379 row->redraw_fringe_bitmaps_p = true;
21380 }
21381
21382
21383 eassert (nrows_scrolled > 0);
21384 rotate_matrix (w->current_matrix,
21385 start_vpos,
21386 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
21387 -nrows_scrolled);
21388
21389
21390 for (row -= nrows_scrolled; row < bottom_row; ++row)
21391 row->enabled_p = false;
21392
21393
21394
21395 if (pt_row)
21396 {
21397 for (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
21398 row < bottom_row
21399 && PT >= MATRIX_ROW_END_CHARPOS (row)
21400 && !row->ends_at_zv_p;
21401 row++)
21402 {
21403 w->cursor.vpos++;
21404 w->cursor.y = row->y;
21405 }
21406 if (row < bottom_row)
21407 {
21408
21409
21410
21411
21412 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
21413 {
21414 if (!set_cursor_from_row (w, row, w->current_matrix,
21415 0, 0, 0, 0))
21416 {
21417 clear_glyph_matrix (w->desired_matrix);
21418 return false;
21419 }
21420 }
21421 else
21422 {
21423 struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
21424 struct glyph *end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
21425
21426 for (; glyph < end
21427 && (!BUFFERP (glyph->object)
21428 || glyph->charpos < PT);
21429 glyph++)
21430 {
21431 w->cursor.hpos++;
21432 w->cursor.x += glyph->pixel_width;
21433 }
21434 }
21435 }
21436 }
21437
21438
21439
21440
21441 if (last_text_row)
21442 adjust_window_ends (w, last_text_row, false);
21443 else
21444 w->window_end_vpos -= nrows_scrolled;
21445
21446 w->window_end_valid = false;
21447 w->desired_matrix->no_scrolling_p = true;
21448
21449 #ifdef GLYPH_DEBUG
21450 debug_method_add (w, "try_window_reusing_current_matrix 2");
21451 #endif
21452 return true;
21453 }
21454
21455 return false;
21456 }
21457
21458
21459
21460
21461
21462
21463
21464 static struct glyph_row *find_last_unchanged_at_beg_row (struct window *);
21465 static struct glyph_row *find_first_unchanged_at_end_row (struct window *,
21466 ptrdiff_t *, ptrdiff_t *);
21467 static struct glyph_row *
21468 find_last_row_displaying_text (struct glyph_matrix *, struct it *,
21469 struct glyph_row *);
21470
21471
21472
21473
21474
21475
21476
21477 static struct glyph_row *
21478 find_last_row_displaying_text (struct glyph_matrix *matrix, struct it *it,
21479 struct glyph_row *start)
21480 {
21481 struct glyph_row *row, *row_found;
21482
21483
21484
21485
21486 row_found = NULL;
21487 row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix);
21488 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21489 {
21490 eassert (row->enabled_p);
21491 row_found = row;
21492 if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y)
21493 break;
21494 ++row;
21495 }
21496
21497 return row_found;
21498 }
21499
21500
21501
21502
21503
21504
21505
21506
21507
21508
21509
21510
21511 static struct glyph_row *
21512 find_last_unchanged_at_beg_row (struct window *w)
21513 {
21514 ptrdiff_t first_changed_pos = BEG + BEG_UNCHANGED;
21515 struct glyph_row *row;
21516 struct glyph_row *row_found = NULL;
21517 int yb = window_text_bottom_y (w);
21518
21519
21520 for (row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21521 MATRIX_ROW_DISPLAYS_TEXT_P (row)
21522 && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos;
21523 ++row)
21524 {
21525 if (
21526
21527 MATRIX_ROW_END_CHARPOS (row) <= first_changed_pos
21528
21529
21530 && !row->ends_at_zv_p
21531
21532
21533
21534 && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
21535 && (row->continued_p
21536 || row->exact_window_width_line_p))
21537
21538
21539
21540
21541
21542
21543
21544 && CHARPOS (row->end.pos) <= ZV)
21545 row_found = row;
21546
21547
21548 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
21549 break;
21550 }
21551
21552 return row_found;
21553 }
21554
21555
21556
21557
21558
21559
21560
21561
21562
21563
21564
21565
21566
21567
21568 static struct glyph_row *
21569 find_first_unchanged_at_end_row (struct window *w,
21570 ptrdiff_t *delta, ptrdiff_t *delta_bytes)
21571 {
21572 struct glyph_row *row;
21573 struct glyph_row *row_found = NULL;
21574
21575 *delta = *delta_bytes = 0;
21576
21577
21578
21579 eassert (w->window_end_valid);
21580
21581
21582
21583
21584 if (w->window_end_pos >= END_UNCHANGED)
21585 return NULL;
21586
21587
21588 row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
21589
21590
21591 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21592 {
21593
21594
21595
21596
21597
21598 ptrdiff_t Z_old =
21599 MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
21600 ptrdiff_t Z_BYTE_old =
21601 MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
21602 ptrdiff_t last_unchanged_pos, last_unchanged_pos_old;
21603 struct glyph_row *first_text_row
21604 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21605
21606 *delta = Z - Z_old;
21607 *delta_bytes = Z_BYTE - Z_BYTE_old;
21608
21609
21610
21611
21612
21613
21614
21615 last_unchanged_pos = Z - END_UNCHANGED + BEG;
21616 last_unchanged_pos_old = last_unchanged_pos - *delta;
21617
21618
21619
21620 for (; row > first_text_row; --row)
21621 {
21622
21623
21624 if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
21625 break;
21626
21627 if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
21628 row_found = row;
21629 }
21630 }
21631
21632 eassert (!row_found || MATRIX_ROW_DISPLAYS_TEXT_P (row_found));
21633
21634 return row_found;
21635 }
21636
21637
21638
21639
21640
21641
21642
21643
21644 static void
21645 sync_frame_with_window_matrix_rows (struct window *w)
21646 {
21647 struct frame *f = XFRAME (w->frame);
21648 struct glyph_row *window_row, *window_row_end, *frame_row;
21649
21650
21651
21652 eassert (BUFFERP (w->contents));
21653 eassert (WINDOW_FULL_WIDTH_P (w));
21654 eassert (!FRAME_WINDOW_P (f));
21655
21656
21657
21658
21659
21660 window_row = w->current_matrix->rows;
21661 window_row_end = window_row + w->current_matrix->nrows;
21662 frame_row = f->current_matrix->rows + WINDOW_TOP_EDGE_LINE (w);
21663 while (window_row < window_row_end)
21664 {
21665 struct glyph *start = window_row->glyphs[LEFT_MARGIN_AREA];
21666 struct glyph *end = window_row->glyphs[LAST_AREA];
21667
21668 frame_row->glyphs[LEFT_MARGIN_AREA] = start;
21669 frame_row->glyphs[TEXT_AREA] = start;
21670 frame_row->glyphs[RIGHT_MARGIN_AREA] = end;
21671 frame_row->glyphs[LAST_AREA] = end;
21672
21673
21674
21675 if (!window_row->enabled_p)
21676 frame_row->enabled_p = false;
21677
21678 ++window_row, ++frame_row;
21679 }
21680 }
21681
21682
21683
21684
21685
21686
21687
21688 struct glyph_row *
21689 row_containing_pos (struct window *w, ptrdiff_t charpos,
21690 struct glyph_row *start, struct glyph_row *end, int dy)
21691 {
21692 struct glyph_row *row = start;
21693 struct glyph_row *best_row = NULL;
21694 ptrdiff_t mindif = BUF_ZV (XBUFFER (w->contents)) + 1;
21695 int last_y;
21696
21697
21698 if (row->tab_line_p)
21699 ++row;
21700 if (row->mode_line_p)
21701 ++row;
21702
21703 if ((end && row >= end) || !row->enabled_p)
21704 return NULL;
21705
21706 last_y = window_text_bottom_y (w) - dy;
21707
21708 while (true)
21709 {
21710
21711 if ((end && row >= end) || !row->enabled_p)
21712 return NULL;
21713
21714
21715
21716 if (MATRIX_ROW_BOTTOM_Y (row) > last_y)
21717 return NULL;
21718
21719
21720 if (! (MATRIX_ROW_END_CHARPOS (row) < charpos
21721 || (MATRIX_ROW_END_CHARPOS (row) == charpos
21722
21723
21724
21725
21726 && !row_for_charpos_p (row, charpos)))
21727 && charpos >= MATRIX_ROW_START_CHARPOS (row))
21728 {
21729 struct glyph *g;
21730
21731 if (NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
21732 || (!best_row && !row->continued_p))
21733 return row;
21734
21735
21736
21737
21738 for (g = row->glyphs[TEXT_AREA];
21739 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
21740 g++)
21741 {
21742 if (!STRINGP (g->object))
21743 {
21744 if (g->charpos > 0 && eabs (g->charpos - charpos) < mindif)
21745 {
21746 mindif = eabs (g->charpos - charpos);
21747 best_row = row;
21748
21749 if (mindif == 0)
21750 return best_row;
21751 }
21752 }
21753 }
21754 }
21755 else if (best_row && !row->continued_p)
21756 return best_row;
21757 ++row;
21758 }
21759 }
21760
21761
21762
21763
21764
21765
21766
21767
21768
21769
21770
21771
21772
21773
21774
21775
21776
21777
21778
21779
21780
21781
21782
21783
21784
21785
21786
21787
21788
21789
21790
21791
21792
21793
21794
21795
21796
21797
21798
21799
21800
21801
21802
21803
21804 static int
21805 try_window_id (struct window *w)
21806 {
21807 struct frame *f = XFRAME (w->frame);
21808 struct glyph_matrix *current_matrix = w->current_matrix;
21809 struct glyph_matrix *desired_matrix = w->desired_matrix;
21810 struct glyph_row *last_unchanged_at_beg_row;
21811 struct glyph_row *first_unchanged_at_end_row;
21812 struct glyph_row *row;
21813 struct glyph_row *bottom_row;
21814 int bottom_vpos;
21815 struct it it;
21816 ptrdiff_t delta = 0, delta_bytes = 0, stop_pos;
21817 int dvpos, dy;
21818 struct text_pos start_pos;
21819 struct run run;
21820 int first_unchanged_at_end_vpos = 0;
21821 struct glyph_row *last_text_row, *last_text_row_at_end;
21822 struct text_pos start;
21823 ptrdiff_t first_changed_charpos, last_changed_charpos;
21824
21825 #ifdef GLYPH_DEBUG
21826 if (inhibit_try_window_id)
21827 return 0;
21828 #endif
21829
21830
21831 #if false
21832 #define GIVE_UP(X) \
21833 do { \
21834 redisplay_trace ("try_window_id give up %d\n", X); \
21835 return 0; \
21836 } while (false)
21837 #else
21838 #define GIVE_UP(X) return 0
21839 #endif
21840
21841 SET_TEXT_POS_FROM_MARKER (start, w->start);
21842
21843
21844
21845 if (MINI_WINDOW_P (w))
21846 GIVE_UP (1);
21847
21848
21849 if (windows_or_buffers_changed || f->cursor_type_changed)
21850 GIVE_UP (2);
21851
21852
21853
21854
21855 if (w->last_overlay_modified != OVERLAY_MODIFF)
21856 GIVE_UP (200);
21857
21858
21859
21860
21861
21862 if (current_buffer->clip_changed
21863 || current_buffer->prevent_redisplay_optimizations_p)
21864 GIVE_UP (3);
21865
21866
21867 if (!FRAME_WINDOW_P (f)
21868 && (!FRAME_LINE_INS_DEL_OK (f)
21869 || !WINDOW_FULL_WIDTH_P (w)))
21870 GIVE_UP (4);
21871
21872
21873 if (PT < CHARPOS (start))
21874 GIVE_UP (5);
21875
21876
21877 if (w->last_modified == 0)
21878 GIVE_UP (6);
21879
21880
21881 if (w->hscroll != 0)
21882 GIVE_UP (7);
21883
21884
21885 if (!w->window_end_valid)
21886 GIVE_UP (8);
21887
21888
21889 if (!NILP (Vshow_trailing_whitespace))
21890 GIVE_UP (11);
21891
21892
21893
21894 if (overlay_arrows_changed_p (false))
21895 GIVE_UP (12);
21896
21897
21898
21899
21900
21901 if (!NILP (BVAR (XBUFFER (w->contents), word_wrap)))
21902 GIVE_UP (21);
21903
21904
21905
21906
21907
21908
21909
21910
21911
21912 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
21913 && NILP (BVAR (XBUFFER (w->contents), bidi_paragraph_direction)))
21914 GIVE_UP (22);
21915
21916
21917
21918 if (!NILP (BVAR (XBUFFER (w->contents), extra_line_spacing)))
21919 GIVE_UP (23);
21920
21921
21922
21923 if (EQ (Vdisplay_line_numbers, Qrelative)
21924 || EQ (Vdisplay_line_numbers, Qvisual)
21925 || (!NILP (Vdisplay_line_numbers)
21926 && NILP (Finternal_lisp_face_equal_p (Qline_number,
21927 Qline_number_current_line,
21928 w->frame))))
21929 GIVE_UP (24);
21930
21931
21932
21933
21934 if (composition_break_at_point)
21935 GIVE_UP (27);
21936
21937
21938
21939
21940
21941 if (MODIFF > SAVE_MODIFF
21942
21943 || BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
21944 {
21945 if (GPT - BEG < BEG_UNCHANGED)
21946 BEG_UNCHANGED = GPT - BEG;
21947 if (Z - GPT < END_UNCHANGED)
21948 END_UNCHANGED = Z - GPT;
21949 }
21950
21951
21952 first_changed_charpos = BEG + BEG_UNCHANGED;
21953 last_changed_charpos = Z - END_UNCHANGED;
21954
21955
21956
21957
21958
21959
21960 row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
21961 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
21962 && ((last_changed_charpos < CHARPOS (start)
21963 && CHARPOS (start) == BEGV)
21964 || (last_changed_charpos < CHARPOS (start) - 1
21965 && FETCH_BYTE (BYTEPOS (start) - 1) == '\n')))
21966 {
21967 ptrdiff_t Z_old, Z_delta, Z_BYTE_old, Z_delta_bytes;
21968 struct glyph_row *r0;
21969
21970
21971
21972 Z_old = MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
21973 Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
21974 Z_delta = Z - Z_old;
21975 Z_delta_bytes = Z_BYTE - Z_BYTE_old;
21976
21977
21978
21979
21980 if (PT >= MATRIX_ROW_END_CHARPOS (row) + Z_delta)
21981 GIVE_UP (13);
21982
21983
21984
21985
21986 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
21987 if (CHARPOS (start) == MATRIX_ROW_START_CHARPOS (r0) + Z_delta
21988 && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + Z_delta_bytes
21989
21990 && !(PT >= MATRIX_ROW_START_CHARPOS (row) + Z_delta
21991 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
21992 {
21993
21994 if (Z_delta || Z_delta_bytes)
21995 {
21996 struct glyph_row *r1
21997 = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
21998 increment_matrix_positions (w->current_matrix,
21999 MATRIX_ROW_VPOS (r0, current_matrix),
22000 MATRIX_ROW_VPOS (r1, current_matrix),
22001 Z_delta, Z_delta_bytes);
22002 }
22003
22004
22005 row = row_containing_pos (w, PT, r0, NULL, 0);
22006 if (row)
22007 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
22008 return 1;
22009 }
22010 }
22011
22012
22013
22014
22015
22016 if (first_changed_charpos >= MATRIX_ROW_END_CHARPOS (row)
22017
22018
22019 && (current_matrix->zv > MATRIX_ROW_END_CHARPOS (row)
22020 || first_changed_charpos == last_changed_charpos))
22021 {
22022 struct glyph_row *r0;
22023
22024
22025
22026
22027 if (PT >= MATRIX_ROW_END_CHARPOS (row))
22028 GIVE_UP (14);
22029
22030
22031
22032
22033 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
22034 if (TEXT_POS_EQUAL_P (start, r0->minpos)
22035
22036 && !(PT >= MATRIX_ROW_START_CHARPOS (row)
22037 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
22038 {
22039
22040
22041 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
22042 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
22043
22044
22045 row = row_containing_pos (w, PT, r0, NULL, 0);
22046 if (row)
22047 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
22048 return 2;
22049 }
22050 }
22051
22052
22053
22054
22055
22056
22057
22058
22059 if (CHARPOS (start) >= first_changed_charpos
22060 && CHARPOS (start) <= last_changed_charpos)
22061 GIVE_UP (15);
22062
22063
22064
22065
22066
22067 row = MATRIX_FIRST_TEXT_ROW (current_matrix);
22068 if (!TEXT_POS_EQUAL_P (start, row->minpos))
22069 GIVE_UP (16);
22070
22071
22072
22073 row = MATRIX_ROW (current_matrix, w->window_end_vpos);
22074 if (MATRIX_ROW_START_CHARPOS (row) == MATRIX_ROW_END_CHARPOS (row))
22075 GIVE_UP (20);
22076
22077
22078
22079
22080
22081 #ifdef HAVE_NTGUI
22082 if (FRAME_W32_P (f) && w32_use_visible_system_caret)
22083 GIVE_UP (25);
22084 #endif
22085
22086
22087
22088
22089
22090
22091
22092 last_unchanged_at_beg_row = find_last_unchanged_at_beg_row (w);
22093 if (last_unchanged_at_beg_row)
22094 {
22095
22096
22097
22098
22099 while ((MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row)
22100 || last_unchanged_at_beg_row->ends_in_newline_from_string_p)
22101 && last_unchanged_at_beg_row > w->current_matrix->rows)
22102 --last_unchanged_at_beg_row;
22103
22104 if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row))
22105 GIVE_UP (17);
22106
22107 if (! init_to_row_end (&it, w, last_unchanged_at_beg_row))
22108 GIVE_UP (18);
22109
22110
22111
22112 if (it.sp > 1
22113 && it.method == GET_FROM_IMAGE && it.image_id == -1)
22114 GIVE_UP (26);
22115 start_pos = it.current.pos;
22116
22117
22118
22119
22120 it.vpos = 1 + MATRIX_ROW_VPOS (last_unchanged_at_beg_row,
22121 current_matrix);
22122 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
22123 it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row);
22124
22125 eassert (it.hpos == 0 && it.current_x == 0);
22126 }
22127 else
22128 {
22129
22130
22131 start_display (&it, w, start);
22132 it.vpos = it.first_vpos;
22133 start_pos = it.current.pos;
22134 }
22135
22136
22137
22138
22139
22140
22141
22142 first_unchanged_at_end_row
22143 = find_first_unchanged_at_end_row (w, &delta, &delta_bytes);
22144 IF_DEBUG (debug_delta = delta);
22145 IF_DEBUG (debug_delta_bytes = delta_bytes);
22146
22147
22148
22149
22150
22151
22152 stop_pos = 0;
22153 if (first_unchanged_at_end_row)
22154 {
22155 eassert (last_unchanged_at_beg_row == NULL
22156 || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
22157
22158
22159
22160
22161
22162 while (MATRIX_ROW_CONTINUATION_LINE_P (first_unchanged_at_end_row)
22163 && MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
22164 && (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
22165 < it.last_visible_y))
22166 ++first_unchanged_at_end_row;
22167
22168 if (!MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
22169 || (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
22170 >= it.last_visible_y))
22171 first_unchanged_at_end_row = NULL;
22172 else
22173 {
22174 stop_pos = (MATRIX_ROW_START_CHARPOS (first_unchanged_at_end_row)
22175 + delta);
22176 first_unchanged_at_end_vpos
22177 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
22178 eassert (stop_pos >= Z - END_UNCHANGED);
22179 }
22180 }
22181 else if (last_unchanged_at_beg_row == NULL)
22182 GIVE_UP (19);
22183
22184
22185 #ifdef GLYPH_DEBUG
22186
22187
22188
22189
22190 eassert (first_unchanged_at_end_row == NULL
22191 || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
22192
22193 debug_last_unchanged_at_beg_vpos
22194 = (last_unchanged_at_beg_row
22195 ? MATRIX_ROW_VPOS (last_unchanged_at_beg_row, current_matrix)
22196 : -1);
22197 debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
22198
22199 #endif
22200
22201
22202
22203
22204
22205 w->cursor.vpos = -1;
22206 last_text_row = NULL;
22207 overlay_arrow_seen = false;
22208 if (it.current_y < it.last_visible_y
22209 && !f->fonts_changed
22210 && (first_unchanged_at_end_row == NULL
22211 || IT_CHARPOS (it) < stop_pos))
22212 it.glyph_row->reversed_p = false;
22213 while (it.current_y < it.last_visible_y
22214 && !f->fonts_changed
22215 && (first_unchanged_at_end_row == NULL
22216 || IT_CHARPOS (it) < stop_pos))
22217 {
22218 if (display_line (&it, -1))
22219 last_text_row = it.glyph_row - 1;
22220 }
22221
22222 if (f->fonts_changed)
22223 return -1;
22224
22225
22226
22227
22228
22229
22230
22231
22232
22233
22234
22235 if (!w->window_end_valid)
22236 {
22237 clear_glyph_matrix (w->desired_matrix);
22238 return -1;
22239 }
22240
22241
22242
22243
22244 if (first_unchanged_at_end_row
22245
22246
22247 && it.current_y < it.last_visible_y)
22248 {
22249 dvpos = (it.vpos
22250 - MATRIX_ROW_VPOS (first_unchanged_at_end_row,
22251 current_matrix));
22252 dy = it.current_y - first_unchanged_at_end_row->y;
22253 run.current_y = first_unchanged_at_end_row->y;
22254 run.desired_y = run.current_y + dy;
22255 run.height = it.last_visible_y - max (run.current_y, run.desired_y);
22256 }
22257 else
22258 {
22259 delta = delta_bytes = dvpos = dy
22260 = run.current_y = run.desired_y = run.height = 0;
22261 first_unchanged_at_end_row = NULL;
22262 }
22263 IF_DEBUG ((debug_dvpos = dvpos, debug_dy = dy));
22264
22265
22266
22267
22268
22269
22270
22271
22272
22273
22274 if (w->cursor.vpos < 0)
22275 {
22276
22277 if (PT < CHARPOS (start_pos)
22278 && last_unchanged_at_beg_row)
22279 {
22280 row = row_containing_pos (w, PT,
22281 MATRIX_FIRST_TEXT_ROW (w->current_matrix),
22282 last_unchanged_at_beg_row + 1, 0);
22283 if (row)
22284 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
22285 }
22286
22287
22288 else if (first_unchanged_at_end_row)
22289 {
22290 row = row_containing_pos (w, PT - delta,
22291 first_unchanged_at_end_row, NULL, 0);
22292 if (row)
22293 set_cursor_from_row (w, row, w->current_matrix, delta,
22294 delta_bytes, dy, dvpos);
22295 }
22296
22297
22298 if (w->cursor.vpos < 0)
22299 {
22300 clear_glyph_matrix (w->desired_matrix);
22301 return -1;
22302 }
22303 }
22304
22305
22306 {
22307 int top_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
22308 int bot_scroll_margin = top_scroll_margin;
22309 int cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
22310
22311 if (window_wants_header_line (w))
22312 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
22313 if (window_wants_tab_line (w))
22314 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
22315
22316 if ((w->cursor.y < top_scroll_margin
22317 && CHARPOS (start) > BEGV)
22318
22319
22320 || (w->cursor.y
22321 + (cursor_row_fully_visible_p (w, false, true, true)
22322 ? 1
22323 : cursor_height + bot_scroll_margin)) > it.last_visible_y)
22324 {
22325 w->cursor.vpos = -1;
22326 clear_glyph_matrix (w->desired_matrix);
22327 return -1;
22328 }
22329 }
22330
22331
22332
22333
22334 if (dy && run.height)
22335 {
22336 update_begin (f);
22337
22338 if (FRAME_WINDOW_P (f))
22339 {
22340 #ifdef HAVE_WINDOW_SYSTEM
22341 gui_update_window_begin (w);
22342 FRAME_RIF (f)->clear_window_mouse_face (w);
22343 FRAME_RIF (f)->scroll_run_hook (w, &run);
22344 gui_update_window_end (w, false, false);
22345 #endif
22346 }
22347 else
22348 {
22349
22350
22351 int from_vpos
22352 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
22353 int from = WINDOW_TOP_EDGE_LINE (w) + from_vpos;
22354 int end = (WINDOW_TOP_EDGE_LINE (w)
22355 + window_wants_tab_line (w)
22356 + window_wants_header_line (w)
22357 + window_internal_height (w));
22358
22359 gui_clear_window_mouse_face (w);
22360
22361
22362 if (dvpos > 0)
22363 {
22364
22365
22366 set_terminal_window (f, end);
22367
22368
22369
22370 if (!FRAME_SCROLL_REGION_OK (f))
22371 ins_del_lines (f, end - dvpos, -dvpos);
22372
22373
22374
22375 ins_del_lines (f, from, dvpos);
22376 }
22377 else if (dvpos < 0)
22378 {
22379
22380
22381 set_terminal_window (f, end);
22382
22383
22384
22385
22386
22387 ins_del_lines (f, from + dvpos, dvpos);
22388
22389
22390
22391 if (!FRAME_SCROLL_REGION_OK (f))
22392 ins_del_lines (f, end + dvpos, -dvpos);
22393 }
22394
22395 set_terminal_window (f, 0);
22396 }
22397
22398 update_end (f);
22399 }
22400
22401
22402
22403
22404 bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
22405 bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix);
22406 if (dvpos < 0)
22407 {
22408 rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
22409 bottom_vpos, dvpos);
22410 clear_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
22411 bottom_vpos);
22412 }
22413 else if (dvpos > 0)
22414 {
22415 rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
22416 bottom_vpos, dvpos);
22417 clear_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
22418 first_unchanged_at_end_vpos + dvpos);
22419 }
22420
22421
22422
22423 if (!FRAME_WINDOW_P (f))
22424 sync_frame_with_window_matrix_rows (w);
22425
22426
22427 if (delta || delta_bytes)
22428 increment_matrix_positions (current_matrix,
22429 first_unchanged_at_end_vpos + dvpos,
22430 bottom_vpos, delta, delta_bytes);
22431
22432
22433 if (dy)
22434 shift_glyph_matrix (w, current_matrix,
22435 first_unchanged_at_end_vpos + dvpos,
22436 bottom_vpos, dy);
22437
22438 if (first_unchanged_at_end_row)
22439 {
22440 first_unchanged_at_end_row += dvpos;
22441 if (first_unchanged_at_end_row->y >= it.last_visible_y
22442 || !MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row))
22443 first_unchanged_at_end_row = NULL;
22444 }
22445
22446
22447
22448 last_text_row_at_end = NULL;
22449 if (dy < 0)
22450 {
22451
22452
22453
22454
22455
22456 int last_vpos = w->window_end_vpos + dvpos;
22457 struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
22458
22459
22460 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_row));
22461
22462
22463
22464
22465 if (MATRIX_ROW_BOTTOM_Y (last_row) - dy >= it.last_visible_y)
22466 {
22467 init_to_row_start (&it, w, last_row);
22468 it.vpos = last_vpos;
22469 it.current_y = last_row->y;
22470 }
22471 else
22472 {
22473 init_to_row_end (&it, w, last_row);
22474 it.vpos = 1 + last_vpos;
22475 it.current_y = MATRIX_ROW_BOTTOM_Y (last_row);
22476 ++last_row;
22477 }
22478
22479
22480
22481 it.continuation_lines_width = last_row->continuation_lines_width;
22482 it.hpos = it.current_x = 0;
22483
22484
22485 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
22486 while (it.current_y < it.last_visible_y && !f->fonts_changed)
22487 {
22488
22489
22490
22491
22492 SET_MATRIX_ROW_ENABLED_P (w->current_matrix, it.vpos, false);
22493 if (display_line (&it, w->cursor.vpos))
22494 last_text_row_at_end = it.glyph_row - 1;
22495 }
22496 }
22497
22498
22499 if (first_unchanged_at_end_row && !last_text_row_at_end)
22500 {
22501
22502
22503
22504
22505 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
22506 row = find_last_row_displaying_text (w->current_matrix, &it,
22507 first_unchanged_at_end_row);
22508 eassume (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
22509 adjust_window_ends (w, row, true);
22510 eassert (w->window_end_bytepos >= 0);
22511 IF_DEBUG (debug_method_add (w, "A"));
22512 }
22513 else if (last_text_row_at_end)
22514 {
22515 adjust_window_ends (w, last_text_row_at_end, false);
22516 eassert (w->window_end_bytepos >= 0);
22517 IF_DEBUG (debug_method_add (w, "B"));
22518 }
22519 else if (last_text_row)
22520 {
22521
22522
22523
22524 adjust_window_ends (w, last_text_row, false);
22525 eassert (w->window_end_bytepos >= 0);
22526 }
22527 else if (first_unchanged_at_end_row == NULL
22528 && last_text_row == NULL
22529 && last_text_row_at_end == NULL)
22530 {
22531
22532
22533 int first_vpos = window_wants_tab_line (w) + window_wants_header_line (w);
22534 int vpos = w->window_end_vpos;
22535 struct glyph_row *current_row = current_matrix->rows + vpos;
22536 struct glyph_row *desired_row = desired_matrix->rows + vpos;
22537
22538 for (row = NULL; !row; --vpos, --current_row, --desired_row)
22539 {
22540 eassert (first_vpos <= vpos);
22541 if (desired_row->enabled_p)
22542 {
22543 if (MATRIX_ROW_DISPLAYS_TEXT_P (desired_row))
22544 row = desired_row;
22545 }
22546 else if (MATRIX_ROW_DISPLAYS_TEXT_P (current_row))
22547 row = current_row;
22548 }
22549
22550 w->window_end_vpos = vpos + 1;
22551 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
22552 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
22553 eassert (w->window_end_bytepos >= 0);
22554 IF_DEBUG (debug_method_add (w, "C"));
22555 }
22556 else
22557 emacs_abort ();
22558
22559 IF_DEBUG ((debug_end_pos = w->window_end_pos,
22560 debug_end_vpos = w->window_end_vpos));
22561
22562
22563 w->window_end_valid = false;
22564 w->desired_matrix->no_scrolling_p = true;
22565 return 3;
22566
22567 #undef GIVE_UP
22568 }
22569
22570
22571
22572
22573
22574
22575
22576 #ifdef GLYPH_DEBUG
22577
22578 void dump_glyph_row (struct glyph_row *, int, int) EXTERNALLY_VISIBLE;
22579 void dump_glyph_matrix (struct glyph_matrix *, int) EXTERNALLY_VISIBLE;
22580 void dump_glyph (struct glyph_row *, struct glyph *, int) EXTERNALLY_VISIBLE;
22581
22582
22583
22584
22585
22586
22587
22588
22589 void
22590 dump_glyph_matrix (struct glyph_matrix *matrix, int glyphs)
22591 {
22592 int i;
22593 for (i = 0; i < matrix->nrows; ++i)
22594 dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
22595 }
22596
22597
22598
22599
22600
22601 void
22602 dump_glyph (struct glyph_row *row, struct glyph *glyph, int area)
22603 {
22604 if (glyph->type == CHAR_GLYPH
22605 || glyph->type == GLYPHLESS_GLYPH)
22606 {
22607 fprintf (stderr,
22608 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22609 glyph - row->glyphs[TEXT_AREA],
22610 (glyph->type == CHAR_GLYPH
22611 ? 'C'
22612 : 'G'),
22613 glyph->charpos,
22614 (BUFFERP (glyph->object)
22615 ? 'B'
22616 : (STRINGP (glyph->object)
22617 ? 'S'
22618 : (NILP (glyph->object)
22619 ? '0'
22620 : '-'))),
22621 glyph->pixel_width,
22622 glyph->u.ch,
22623 (glyph->u.ch < 0x80 && glyph->u.ch >= ' '
22624 ? (int) glyph->u.ch
22625 : '.'),
22626 glyph->face_id,
22627 glyph->left_box_line_p,
22628 glyph->right_box_line_p);
22629 }
22630 else if (glyph->type == STRETCH_GLYPH)
22631 {
22632 fprintf (stderr,
22633 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22634 glyph - row->glyphs[TEXT_AREA],
22635 'S',
22636 glyph->charpos,
22637 (BUFFERP (glyph->object)
22638 ? 'B'
22639 : (STRINGP (glyph->object)
22640 ? 'S'
22641 : (NILP (glyph->object)
22642 ? '0'
22643 : '-'))),
22644 glyph->pixel_width,
22645 0u,
22646 ' ',
22647 glyph->face_id,
22648 glyph->left_box_line_p,
22649 glyph->right_box_line_p);
22650 }
22651 else if (glyph->type == IMAGE_GLYPH)
22652 {
22653 fprintf (stderr,
22654 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22655 glyph - row->glyphs[TEXT_AREA],
22656 'I',
22657 glyph->charpos,
22658 (BUFFERP (glyph->object)
22659 ? 'B'
22660 : (STRINGP (glyph->object)
22661 ? 'S'
22662 : (NILP (glyph->object)
22663 ? '0'
22664 : '-'))),
22665 glyph->pixel_width,
22666 (unsigned int) glyph->u.img_id,
22667 '.',
22668 glyph->face_id,
22669 glyph->left_box_line_p,
22670 glyph->right_box_line_p);
22671 }
22672 else if (glyph->type == COMPOSITE_GLYPH)
22673 {
22674 fprintf (stderr,
22675 " %5"pD"d %c %9"pD"d %c %3d 0x%06x",
22676 glyph - row->glyphs[TEXT_AREA],
22677 '+',
22678 glyph->charpos,
22679 (BUFFERP (glyph->object)
22680 ? 'B'
22681 : (STRINGP (glyph->object)
22682 ? 'S'
22683 : (NILP (glyph->object)
22684 ? '0'
22685 : '-'))),
22686 glyph->pixel_width,
22687 (unsigned int) glyph->u.cmp.id);
22688 if (glyph->u.cmp.automatic)
22689 fprintf (stderr,
22690 "[%d-%d]",
22691 glyph->slice.cmp.from, glyph->slice.cmp.to);
22692 fprintf (stderr, " . %4d %1.1d%1.1d\n",
22693 glyph->face_id,
22694 glyph->left_box_line_p,
22695 glyph->right_box_line_p);
22696 }
22697 else if (glyph->type == XWIDGET_GLYPH)
22698 {
22699 #ifndef HAVE_XWIDGETS
22700 eassume (false);
22701 #else
22702 fprintf (stderr,
22703 " %5td %4c %6td %c %3d %7p %c %4d %1.1d%1.1d\n",
22704 glyph - row->glyphs[TEXT_AREA],
22705 'X',
22706 glyph->charpos,
22707 (BUFFERP (glyph->object)
22708 ? 'B'
22709 : (STRINGP (glyph->object)
22710 ? 'S'
22711 : '-')),
22712 glyph->pixel_width,
22713 glyph->u.xwidget,
22714 '.',
22715 glyph->face_id,
22716 glyph->left_box_line_p,
22717 glyph->right_box_line_p);
22718 #endif
22719 }
22720 }
22721
22722
22723
22724
22725
22726
22727
22728 void
22729 dump_glyph_row (struct glyph_row *row, int vpos, int glyphs)
22730 {
22731 if (glyphs != 1)
22732 {
22733 fputs (("Row Start End Used oE><\\CTZFesm X Y W H V A P\n"
22734 "==============================================================================\n"),
22735 stderr);
22736 fprintf (stderr, "%3d %9"pD"d %9"pD"d %4d %1.1d%1.1d%1.1d%1.1d\
22737 %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d %4d %4d %4d %4d\n",
22738 vpos,
22739 MATRIX_ROW_START_CHARPOS (row),
22740 MATRIX_ROW_END_CHARPOS (row),
22741 row->used[TEXT_AREA],
22742 row->contains_overlapping_glyphs_p,
22743 row->enabled_p,
22744 row->truncated_on_left_p,
22745 row->truncated_on_right_p,
22746 row->continued_p,
22747 MATRIX_ROW_CONTINUATION_LINE_P (row),
22748 MATRIX_ROW_DISPLAYS_TEXT_P (row),
22749 row->ends_at_zv_p,
22750 row->fill_line_p,
22751 row->ends_in_middle_of_char_p,
22752 row->starts_in_middle_of_char_p,
22753 row->mouse_face_p,
22754 row->x,
22755 row->y,
22756 row->pixel_width,
22757 row->height,
22758 row->visible_height,
22759 row->ascent,
22760 row->phys_ascent);
22761
22762 fprintf (stderr, " %9"pD"d %9"pD"d\t%5d\n", row->start.overlay_string_index,
22763 row->end.overlay_string_index,
22764 row->continuation_lines_width);
22765 fprintf (stderr, " %9"pD"d %9"pD"d\n",
22766 CHARPOS (row->start.string_pos),
22767 CHARPOS (row->end.string_pos));
22768 fprintf (stderr, " %9d %9d\n", row->start.dpvec_index,
22769 row->end.dpvec_index);
22770 }
22771
22772 if (glyphs > 1)
22773 {
22774 int area;
22775
22776 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
22777 {
22778 struct glyph *glyph = row->glyphs[area];
22779 struct glyph *glyph_end = glyph + row->used[area];
22780
22781
22782 if (area == TEXT_AREA && glyph == glyph_end && glyph->charpos > 0)
22783 ++glyph_end;
22784
22785 if (glyph < glyph_end)
22786 fputs (" Glyph# Type Pos O W Code C Face LR\n",
22787 stderr);
22788
22789 for (; glyph < glyph_end; ++glyph)
22790 dump_glyph (row, glyph, area);
22791 }
22792 }
22793 else if (glyphs == 1)
22794 {
22795 int area;
22796 char s[SHRT_MAX + 4];
22797
22798 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
22799 {
22800 int i;
22801
22802 for (i = 0; i < row->used[area]; ++i)
22803 {
22804 struct glyph *glyph = row->glyphs[area] + i;
22805 if (i == row->used[area] - 1
22806 && area == TEXT_AREA
22807 && NILP (glyph->object)
22808 && glyph->type == CHAR_GLYPH
22809 && glyph->u.ch == ' ')
22810 {
22811 strcpy (&s[i], "[\\n]");
22812 i += 4;
22813 }
22814 else if (glyph->type == CHAR_GLYPH
22815 && glyph->u.ch < 0x80
22816 && glyph->u.ch >= ' ')
22817 s[i] = glyph->u.ch;
22818 else
22819 s[i] = '.';
22820 }
22821
22822 s[i] = '\0';
22823 fprintf (stderr, "%3d: (%d) '%s'\n", vpos, row->enabled_p, s);
22824 }
22825 }
22826 }
22827
22828
22829 DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
22830 Sdump_glyph_matrix, 0, 1, "p",
22831 doc:
22832
22833
22834
22835
22836
22837 )
22838 (Lisp_Object glyphs)
22839 {
22840 struct window *w = XWINDOW (selected_window);
22841 struct buffer *buffer = XBUFFER (w->contents);
22842
22843 fprintf (stderr, "PT = %"pD"d, BEGV = %"pD"d. ZV = %"pD"d\n",
22844 BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
22845 fprintf (stderr, "Cursor x = %d, y = %d, hpos = %d, vpos = %d\n",
22846 w->cursor.x, w->cursor.y, w->cursor.hpos, w->cursor.vpos);
22847 fputs ("=============================================\n", stderr);
22848 dump_glyph_matrix (w->current_matrix,
22849 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 0);
22850 return Qnil;
22851 }
22852
22853
22854 DEFUN ("dump-frame-glyph-matrix", Fdump_frame_glyph_matrix,
22855 Sdump_frame_glyph_matrix, 0, 0, "", doc:
22856 )
22857 (void)
22858 {
22859 struct frame *f = XFRAME (selected_frame);
22860
22861 if (f->current_matrix)
22862 dump_glyph_matrix (f->current_matrix, 1);
22863 else
22864 fputs ("*** This frame doesn't have a frame glyph matrix ***\n", stderr);
22865 return Qnil;
22866 }
22867
22868
22869 DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 2, "P",
22870 doc:
22871
22872
22873
22874
22875 )
22876 (Lisp_Object row, Lisp_Object glyphs)
22877 {
22878 struct glyph_matrix *matrix;
22879 EMACS_INT vpos;
22880
22881 if (NILP (row))
22882 {
22883 int d1, d2, d3, d4, d5, ypos;
22884 bool visible_p = pos_visible_p (XWINDOW (selected_window), PT,
22885 &d1, &d2, &d3, &d4, &d5, &ypos);
22886 if (visible_p)
22887 vpos = ypos;
22888 else
22889 vpos = 0;
22890 }
22891 else
22892 {
22893 CHECK_FIXNUM (row);
22894 vpos = XFIXNUM (row);
22895 }
22896 matrix = XWINDOW (selected_window)->current_matrix;
22897 if (vpos >= 0 && vpos < matrix->nrows)
22898 dump_glyph_row (MATRIX_ROW (matrix, vpos),
22899 vpos,
22900 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22901 return Qnil;
22902 }
22903
22904
22905 DEFUN ("dump-tab-bar-row", Fdump_tab_bar_row, Sdump_tab_bar_row, 1, 2, "P",
22906 doc:
22907
22908
22909
22910
22911
22912
22913 )
22914 (Lisp_Object row, Lisp_Object glyphs)
22915 {
22916 #if defined (HAVE_WINDOW_SYSTEM)
22917 struct frame *sf = SELECTED_FRAME ();
22918 struct glyph_matrix *m = WINDOWP (sf->tab_bar_window)
22919 ? XWINDOW (sf->tab_bar_window)->current_matrix
22920 : sf->current_matrix;
22921 EMACS_INT vpos;
22922
22923 if (NILP (row))
22924 vpos = WINDOWP (sf->tab_bar_window) ? 0 :
22925 FRAME_MENU_BAR_LINES (sf) > 0 ? 1 : 0;
22926 else
22927 {
22928 CHECK_FIXNUM (row);
22929 vpos = XFIXNUM (row);
22930 }
22931 if (vpos >= 0 && vpos < m->nrows)
22932 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
22933 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22934 #endif
22935 return Qnil;
22936 }
22937
22938 DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row, 1, 2, "P",
22939 doc:
22940
22941
22942
22943
22944
22945
22946 )
22947 (Lisp_Object row, Lisp_Object glyphs)
22948 {
22949 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
22950 struct frame *sf = SELECTED_FRAME ();
22951 struct glyph_matrix *m = XWINDOW (sf->tool_bar_window)->current_matrix;
22952 EMACS_INT vpos;
22953
22954 if (NILP (row))
22955 vpos = 0;
22956 else
22957 {
22958 CHECK_FIXNUM (row);
22959 vpos = XFIXNUM (row);
22960 }
22961 if (vpos >= 0 && vpos < m->nrows)
22962 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
22963 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22964 #endif
22965 return Qnil;
22966 }
22967
22968
22969 DEFUN ("trace-redisplay", Ftrace_redisplay, Strace_redisplay, 0, 1, "P",
22970 doc:
22971 )
22972 (Lisp_Object arg)
22973 {
22974 if (NILP (arg))
22975 trace_redisplay_p = !trace_redisplay_p;
22976 else
22977 {
22978 arg = Fprefix_numeric_value (arg);
22979 trace_redisplay_p = XFIXNUM (arg) > 0;
22980 }
22981
22982 return Qnil;
22983 }
22984
22985
22986 DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "",
22987 doc:
22988 )
22989 (ptrdiff_t nargs, Lisp_Object *args)
22990 {
22991 Lisp_Object s = Fformat (nargs, args);
22992 fwrite (SDATA (s), 1, SBYTES (s), stderr);
22993 return Qnil;
22994 }
22995
22996 #endif
22997
22998
22999
23000
23001
23002
23003
23004
23005
23006
23007
23008 static struct glyph_row *
23009 get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string)
23010 {
23011 struct frame *f = XFRAME (WINDOW_FRAME (w));
23012 struct buffer *buffer = XBUFFER (w->contents);
23013 struct buffer *old = current_buffer;
23014 const unsigned char *arrow_string = SDATA (overlay_arrow_string);
23015 ptrdiff_t arrow_len = SBYTES (overlay_arrow_string), char_num = 0;
23016 const unsigned char *arrow_end = arrow_string + arrow_len;
23017 const unsigned char *p;
23018 struct it it;
23019 bool multibyte_p;
23020 int n_glyphs_before;
23021
23022 set_buffer_temp (buffer);
23023 init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID);
23024 scratch_glyph_row.reversed_p = false;
23025 it.glyph_row->used[TEXT_AREA] = 0;
23026 SET_TEXT_POS (it.position, 0, 0);
23027
23028 multibyte_p = !NILP (BVAR (buffer, enable_multibyte_characters));
23029 p = arrow_string;
23030 while (p < arrow_end)
23031 {
23032 Lisp_Object face, ilisp;
23033
23034
23035 if (multibyte_p)
23036 it.c = it.char_to_display = check_char_and_length (p, &it.len);
23037 else
23038 {
23039 it.c = it.char_to_display = *p, it.len = 1;
23040 if (! ASCII_CHAR_P (it.c))
23041 it.char_to_display = BYTE8_TO_CHAR (it.c);
23042 }
23043 p += it.len;
23044
23045
23046 ilisp = make_fixnum (char_num++);
23047 face = Fget_text_property (ilisp, Qface, overlay_arrow_string);
23048 it.face_id = compute_char_face (f, it.char_to_display, face);
23049
23050
23051 n_glyphs_before = it.glyph_row->used[TEXT_AREA];
23052 SET_TEXT_POS (it.position, -1, -1);
23053 PRODUCE_GLYPHS (&it);
23054
23055
23056
23057 if (it.current_x > it.last_visible_x)
23058 {
23059 it.glyph_row->used[TEXT_AREA] = n_glyphs_before;
23060 break;
23061 }
23062 }
23063
23064 set_buffer_temp (old);
23065 return it.glyph_row;
23066 }
23067
23068
23069
23070
23071
23072 static void
23073 insert_left_trunc_glyphs (struct it *it)
23074 {
23075 struct it truncate_it;
23076 struct glyph *from, *end, *to, *toend;
23077
23078 eassert (!FRAME_WINDOW_P (it->f)
23079 || (!it->glyph_row->reversed_p
23080 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
23081 || (it->glyph_row->reversed_p
23082 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0));
23083
23084
23085 truncate_it = *it;
23086 truncate_it.current_x = 0;
23087 truncate_it.face_id = DEFAULT_FACE_ID;
23088 truncate_it.glyph_row = &scratch_glyph_row;
23089 truncate_it.area = TEXT_AREA;
23090 truncate_it.glyph_row->used[TEXT_AREA] = 0;
23091 CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
23092 truncate_it.object = Qnil;
23093 produce_special_glyphs (&truncate_it, IT_TRUNCATION);
23094
23095
23096 if (!it->glyph_row->reversed_p)
23097 {
23098 short tused = truncate_it.glyph_row->used[TEXT_AREA];
23099
23100 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
23101 end = from + tused;
23102 to = it->glyph_row->glyphs[TEXT_AREA];
23103 toend = to + it->glyph_row->used[TEXT_AREA];
23104 if (FRAME_WINDOW_P (it->f))
23105 {
23106
23107
23108
23109
23110
23111
23112
23113 int w = 0;
23114 struct glyph *g = to;
23115 short used;
23116
23117
23118
23119
23120
23121
23122 it->glyph_row->x = 0;
23123 while (g < toend && w < it->truncation_pixel_width)
23124 {
23125 w += g->pixel_width;
23126 ++g;
23127 }
23128 if (g - to - tused > 0)
23129 {
23130 memmove (to + tused, g, (toend - g) * sizeof(*g));
23131 it->glyph_row->used[TEXT_AREA] -= g - to - tused;
23132 }
23133 used = it->glyph_row->used[TEXT_AREA];
23134 if (it->glyph_row->truncated_on_right_p
23135 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0
23136 && it->glyph_row->glyphs[TEXT_AREA][used - 2].type
23137 == STRETCH_GLYPH)
23138 {
23139 int extra = w - it->truncation_pixel_width;
23140
23141 it->glyph_row->glyphs[TEXT_AREA][used - 2].pixel_width += extra;
23142 }
23143 }
23144
23145 while (from < end)
23146 *to++ = *from++;
23147
23148
23149 if (!FRAME_WINDOW_P (it->f))
23150 {
23151 while (to < toend && CHAR_GLYPH_PADDING_P (*to))
23152 {
23153 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
23154 while (from < end)
23155 *to++ = *from++;
23156 }
23157 }
23158
23159 if (to > toend)
23160 it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA];
23161 }
23162 else
23163 {
23164 short tused = truncate_it.glyph_row->used[TEXT_AREA];
23165
23166
23167
23168 end = truncate_it.glyph_row->glyphs[TEXT_AREA];
23169 from = end + truncate_it.glyph_row->used[TEXT_AREA] - 1;
23170 toend = it->glyph_row->glyphs[TEXT_AREA];
23171 to = toend + it->glyph_row->used[TEXT_AREA] - 1;
23172 if (FRAME_WINDOW_P (it->f))
23173 {
23174 int w = 0;
23175 struct glyph *g = to;
23176
23177 while (g >= toend && w < it->truncation_pixel_width)
23178 {
23179 w += g->pixel_width;
23180 --g;
23181 }
23182 if (to - g - tused > 0)
23183 to = g + tused;
23184 if (it->glyph_row->truncated_on_right_p
23185 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
23186 && it->glyph_row->glyphs[TEXT_AREA][1].type == STRETCH_GLYPH)
23187 {
23188 int extra = w - it->truncation_pixel_width;
23189
23190 it->glyph_row->glyphs[TEXT_AREA][1].pixel_width += extra;
23191 }
23192 }
23193
23194 while (from >= end && to >= toend)
23195 *to-- = *from--;
23196 if (!FRAME_WINDOW_P (it->f))
23197 {
23198 while (to >= toend && CHAR_GLYPH_PADDING_P (*to))
23199 {
23200 from =
23201 truncate_it.glyph_row->glyphs[TEXT_AREA]
23202 + truncate_it.glyph_row->used[TEXT_AREA] - 1;
23203 while (from >= end && to >= toend)
23204 *to-- = *from--;
23205 }
23206 }
23207 if (from >= end)
23208 {
23209
23210
23211 int move_by = from - end + 1;
23212 struct glyph *g0 = it->glyph_row->glyphs[TEXT_AREA];
23213 struct glyph *g = g0 + it->glyph_row->used[TEXT_AREA] - 1;
23214
23215 for ( ; g >= g0; g--)
23216 g[move_by] = *g;
23217 while (from >= end)
23218 *to-- = *from--;
23219 it->glyph_row->used[TEXT_AREA] += move_by;
23220 }
23221 }
23222 }
23223
23224
23225 unsigned
23226 row_hash (struct glyph_row *row)
23227 {
23228 int area, k;
23229 unsigned hashval = 0;
23230
23231 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
23232 for (k = 0; k < row->used[area]; ++k)
23233 hashval = ((((hashval << 4) + (hashval >> 24)) & 0x0fffffff)
23234 + row->glyphs[area][k].u.val
23235 + row->glyphs[area][k].face_id
23236 + row->glyphs[area][k].padding_p
23237 + (row->glyphs[area][k].type << 2));
23238
23239 return hashval;
23240 }
23241
23242
23243
23244
23245
23246
23247
23248
23249
23250
23251
23252
23253
23254
23255
23256
23257
23258
23259 static void
23260 compute_line_metrics (struct it *it)
23261 {
23262 struct glyph_row *row = it->glyph_row;
23263
23264 if (FRAME_WINDOW_P (it->f))
23265 {
23266 int i, min_y, max_y;
23267
23268
23269
23270
23271 if (row->height == 0)
23272 {
23273 if (it->max_ascent + it->max_descent == 0)
23274 it->max_descent = it->max_phys_descent = FRAME_LINE_HEIGHT (it->f);
23275 row->ascent = it->max_ascent;
23276 row->height = it->max_ascent + it->max_descent;
23277 row->phys_ascent = it->max_phys_ascent;
23278 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
23279 row->extra_line_spacing = it->max_extra_line_spacing;
23280 }
23281
23282
23283 row->pixel_width = row->x;
23284 for (i = 0; i < row->used[TEXT_AREA]; ++i)
23285 row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
23286
23287 eassert (row->pixel_width >= 0);
23288 eassert (row->ascent >= 0 && row->height > 0);
23289
23290 row->overlapping_p = (MATRIX_ROW_OVERLAPS_SUCC_P (row)
23291 || MATRIX_ROW_OVERLAPS_PRED_P (row));
23292
23293
23294
23295
23296 if (row == MATRIX_FIRST_TEXT_ROW (it->w->desired_matrix)
23297 && row->phys_ascent > row->ascent)
23298 {
23299 row->height += row->phys_ascent - row->ascent;
23300 row->ascent = row->phys_ascent;
23301 }
23302
23303
23304 row->visible_height = row->height;
23305
23306 min_y = WINDOW_TAB_LINE_HEIGHT (it->w) + WINDOW_HEADER_LINE_HEIGHT (it->w);
23307 max_y = WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w);
23308
23309 if (row->y < min_y)
23310 row->visible_height -= min_y - row->y;
23311 if (row->y + row->height > max_y)
23312 row->visible_height -= row->y + row->height - max_y;
23313 }
23314 else
23315 {
23316 row->pixel_width = row->used[TEXT_AREA];
23317 if (row->continued_p)
23318 row->pixel_width -= it->continuation_pixel_width;
23319 else if (row->truncated_on_right_p)
23320 row->pixel_width -= it->truncation_pixel_width;
23321 row->ascent = row->phys_ascent = 0;
23322 row->height = row->phys_height = row->visible_height = 1;
23323 row->extra_line_spacing = 0;
23324 }
23325
23326
23327 row->hash = row_hash (row);
23328
23329 it->max_ascent = it->max_descent = 0;
23330 it->max_phys_ascent = it->max_phys_descent = 0;
23331 }
23332
23333
23334 static void
23335 clear_position (struct it *it)
23336 {
23337 it->position.charpos = 0;
23338 it->position.bytepos = 0;
23339 }
23340
23341
23342
23343
23344
23345
23346
23347
23348
23349
23350
23351
23352
23353 static bool
23354 append_space_for_newline (struct it *it, bool default_face_p)
23355 {
23356 int n = it->glyph_row->used[TEXT_AREA];
23357
23358 if (it->glyph_row->glyphs[TEXT_AREA] + n
23359 < it->glyph_row->glyphs[1 + TEXT_AREA])
23360 {
23361
23362
23363
23364
23365 enum display_element_type saved_what = it->what;
23366 int saved_c = it->c, saved_len = it->len;
23367 int saved_char_to_display = it->char_to_display;
23368 int saved_x = it->current_x;
23369 const int saved_face_id = it->face_id;
23370 bool saved_box_end = it->end_of_box_run_p;
23371 struct text_pos saved_pos = it->position;
23372 Lisp_Object saved_object = it->object;
23373 struct face *face;
23374
23375 it->what = IT_CHARACTER;
23376 clear_position (it);
23377 it->object = Qnil;
23378 it->len = 1;
23379
23380 int char_width = 1;
23381
23382 if (default_face_p
23383 #ifdef HAVE_WINDOW_SYSTEM
23384 || FRAME_WINDOW_P (it->f)
23385 #endif
23386 )
23387 {
23388 const int local_default_face_id =
23389 lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
23390
23391 #ifdef HAVE_WINDOW_SYSTEM
23392 if (FRAME_WINDOW_P (it->f))
23393 {
23394 struct face *default_face
23395 = FACE_FROM_ID (it->f, local_default_face_id);
23396 struct font *font = (default_face->font
23397 ? default_face->font
23398 : FRAME_FONT (it->f));
23399 char_width = (font->average_width
23400 ? font->average_width
23401 : font->space_width);
23402 }
23403 #endif
23404 if (default_face_p)
23405 it->face_id = local_default_face_id;
23406 }
23407
23408
23409
23410
23411 const int indicator_column =
23412 fill_column_indicator_column (it, char_width);
23413 int saved_end_of_box_run = it->end_of_box_run_p;
23414 bool should_keep_end_of_box_run = false;
23415
23416 if (it->current_x == indicator_column)
23417 {
23418 it->c = it->char_to_display
23419 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23420 it->face_id
23421 = merge_faces (it->w, Qfill_column_indicator,
23422 0, saved_face_id);
23423 face = FACE_FROM_ID (it->f, it->face_id);
23424 }
23425 else
23426 {
23427 it->c = it->char_to_display = ' ';
23428
23429
23430
23431 face = FACE_FROM_ID (it->f, it->face_id);
23432 it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
23433
23434
23435
23436
23437 if (!(it->glyph_row->reversed_p
23438
23439
23440
23441 && saved_x + FRAME_COLUMN_WIDTH (it->f) < it->last_visible_x))
23442 should_keep_end_of_box_run = true;
23443 }
23444 PRODUCE_GLYPHS (it);
23445
23446
23447 if (should_keep_end_of_box_run)
23448 it->end_of_box_run_p = saved_end_of_box_run;
23449 #ifdef HAVE_WINDOW_SYSTEM
23450 if (FRAME_WINDOW_P (it->f))
23451 {
23452
23453
23454
23455 struct glyph *g = it->glyph_row->glyphs[TEXT_AREA] + n;
23456 struct font *font = face->font ? face->font : FRAME_FONT (it->f);
23457 if (n == 0)
23458 {
23459 Lisp_Object height, total_height;
23460 int extra_line_spacing = it->extra_line_spacing;
23461 int boff = font->baseline_offset;
23462
23463 if (font->vertical_centering)
23464 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
23465
23466 it->object = saved_object;
23467 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
23468
23469
23470 height = get_it_property (it, Qline_height);
23471 if (CONSP (height)
23472 && CONSP (XCDR (height))
23473 && NILP (XCDR (XCDR (height))))
23474 {
23475 total_height = XCAR (XCDR (height));
23476 height = XCAR (height);
23477 }
23478 else
23479 total_height = Qnil;
23480 height = calc_line_height_property (it, height, font, boff, true);
23481
23482 if (it->override_ascent >= 0)
23483 {
23484 it->ascent = it->override_ascent;
23485 it->descent = it->override_descent;
23486 boff = it->override_boff;
23487 }
23488 if (EQ (height, Qt))
23489 extra_line_spacing = 0;
23490 else
23491 {
23492 Lisp_Object spacing;
23493
23494 it->phys_ascent = it->ascent;
23495 it->phys_descent = it->descent;
23496 if (!NILP (height)
23497 && XFIXNUM (height) > it->ascent + it->descent)
23498 it->ascent = XFIXNUM (height) - it->descent;
23499
23500 if (!NILP (total_height))
23501 spacing = calc_line_height_property (it, total_height, font,
23502 boff, false);
23503 else
23504 {
23505 spacing = get_it_property (it, Qline_spacing);
23506 spacing = calc_line_height_property (it, spacing, font,
23507 boff, false);
23508 }
23509 if (FIXNUMP (spacing))
23510 {
23511 extra_line_spacing = XFIXNUM (spacing);
23512 if (!NILP (total_height))
23513 extra_line_spacing -= (it->phys_ascent + it->phys_descent);
23514 }
23515 }
23516 if (extra_line_spacing > 0)
23517 {
23518 it->descent += extra_line_spacing;
23519 if (extra_line_spacing > it->max_extra_line_spacing)
23520 it->max_extra_line_spacing = extra_line_spacing;
23521 }
23522 it->max_ascent = it->ascent;
23523 it->max_descent = it->descent;
23524
23525 it->glyph_row->height = 0;
23526 }
23527
23528 g->ascent = it->max_ascent;
23529 g->descent = it->max_descent;
23530 }
23531 #endif
23532 it->override_ascent = -1;
23533 it->constrain_row_ascent_descent_p = false;
23534 it->current_x = saved_x;
23535 it->object = saved_object;
23536 it->position = saved_pos;
23537 it->what = saved_what;
23538 it->face_id = saved_face_id;
23539 it->len = saved_len;
23540 it->c = saved_c;
23541 it->char_to_display = saved_char_to_display;
23542 it->end_of_box_run_p = saved_box_end;
23543 return true;
23544 }
23545
23546 return false;
23547 }
23548
23549
23550
23551
23552
23553
23554
23555
23556
23557 static void
23558 extend_face_to_end_of_line (struct it *it)
23559 {
23560 struct frame *f = it->f;
23561
23562
23563
23564
23565
23566
23567 if ((it->current_x >= it->last_visible_x
23568 + (!FRAME_WINDOW_P (f)
23569 && it->glyph_row->reversed_p
23570 && !it->glyph_row->continued_p))
23571
23572
23573 && !(WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23574 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0))
23575 return;
23576
23577 specpdl_ref count = SPECPDL_INDEX ();
23578
23579
23580
23581
23582 specbind (Qinhibit_quit, Qt);
23583
23584 struct face *default_face =
23585 FACE_FROM_ID_OR_NULL (f, lookup_basic_face (it->w, f, DEFAULT_FACE_ID));
23586 if (!default_face)
23587 return;
23588
23589 const int extend_face_id =
23590 (it->face_id == default_face->id || it->s != NULL)
23591 ? it->face_id
23592 : (it->glyph_row->ends_at_zv_p
23593 ? default_face->id
23594 : face_at_pos (it, LFACE_EXTEND_INDEX));
23595 unbind_to (count, Qnil);
23596
23597
23598
23599
23600 struct face *face = FACE_FROM_ID (f, (it->face_before_selective_p
23601 ? it->saved_face_id
23602 : extend_face_id));
23603
23604 if (FRAME_WINDOW_P (f)
23605 && MATRIX_ROW_DISPLAYS_TEXT_P (it->glyph_row)
23606 && face->box == FACE_NO_BOX
23607 && face->underline == FACE_NO_UNDERLINE
23608 && !face->overline_p
23609 && !face->strike_through_p
23610 && face->background == FRAME_BACKGROUND_PIXEL (f)
23611 #ifdef HAVE_WINDOW_SYSTEM
23612 && !face->stipple
23613 #endif
23614 && !it->glyph_row->reversed_p
23615 && !display_fill_column_indicator)
23616 return;
23617
23618
23619
23620 it->glyph_row->fill_line_p = true;
23621
23622 const int orig_face_id = it->face_id;
23623
23624
23625
23626
23627
23628 if (!ASCII_CHAR_P (it->c))
23629 it->face_id = FACE_FOR_CHAR (f, face, 0, -1, Qnil);
23630
23631
23632 #ifdef HAVE_WINDOW_SYSTEM
23633 if (FRAME_WINDOW_P (f))
23634 {
23635
23636
23637 if (it->glyph_row->used[TEXT_AREA] == 0)
23638 {
23639 it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
23640 it->glyph_row->glyphs[TEXT_AREA][0].face_id = face->id;
23641 it->glyph_row->used[TEXT_AREA] = 1;
23642 }
23643
23644
23645 if (!(it->glyph_row->mode_line_p
23646 || (WINDOWP (f->tab_bar_window)
23647 && it->w == XWINDOW (f->tab_bar_window))
23648 #ifndef HAVE_EXT_TOOL_BAR
23649 || (WINDOWP (f->tool_bar_window)
23650 && it->w == XWINDOW (f->tool_bar_window))
23651 #endif
23652 ))
23653 {
23654 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23655 && it->glyph_row->used[LEFT_MARGIN_AREA] == 0)
23656 {
23657 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0] = space_glyph;
23658 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0].face_id =
23659 default_face->id;
23660 it->glyph_row->used[LEFT_MARGIN_AREA] = 1;
23661 }
23662 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
23663 && it->glyph_row->used[RIGHT_MARGIN_AREA] == 0)
23664 {
23665 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0] = space_glyph;
23666 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0].face_id =
23667 default_face->id;
23668 it->glyph_row->used[RIGHT_MARGIN_AREA] = 1;
23669 }
23670
23671 struct font *font = (default_face->font
23672 ? default_face->font
23673 : FRAME_FONT (f));
23674
23675 const int char_width = (font->average_width
23676 ? font->average_width
23677 : font->space_width);
23678
23679 const int indicator_column =
23680 fill_column_indicator_column (it, char_width);
23681
23682 const char saved_char = it->char_to_display;
23683 const struct text_pos saved_pos = it->position;
23684 const bool saved_avoid_cursor = it->avoid_cursor_p;
23685 const bool saved_box_start = it->start_of_box_run_p;
23686 Lisp_Object save_object = it->object;
23687 const int saved_face_id = it->face_id;
23688
23689 it->face_id = extend_face_id;
23690 it->avoid_cursor_p = true;
23691 it->object = Qnil;
23692
23693 const int stretch_height = it->ascent + it->descent;
23694 const int stretch_ascent =
23695 (stretch_height * FONT_BASE (font)) / FONT_HEIGHT (font);
23696
23697 if (indicator_column >= 0
23698 && indicator_column > it->current_x
23699 && indicator_column < it->last_visible_x)
23700 {
23701
23702
23703
23704
23705 const int stretch_width =
23706 indicator_column - it->current_x - char_width;
23707
23708 clear_position (it);
23709
23710
23711
23712 if (stretch_width > 0)
23713 {
23714 append_stretch_glyph (it, Qnil, stretch_width,
23715 stretch_height, stretch_ascent);
23716 }
23717
23718
23719
23720 if (it->current_x < indicator_column)
23721 {
23722 const int save_face_id = it->face_id;
23723 const int save_ascent = it->ascent;
23724 const int save_descent = it->descent;
23725 it->char_to_display
23726 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23727 it->face_id
23728 = merge_faces (it->w, Qfill_column_indicator,
23729 0, extend_face_id);
23730 PRODUCE_GLYPHS (it);
23731 it->face_id = save_face_id;
23732 it->ascent = save_ascent;
23733 it->descent = save_descent;
23734 }
23735 }
23736
23737
23738
23739 if (!it->glyph_row->reversed_p)
23740 {
23741 const int stretch_width = it->last_visible_x - it->current_x;
23742
23743 if (stretch_width > 0)
23744 {
23745 clear_position (it);
23746 append_stretch_glyph (it, Qnil, stretch_width,
23747 stretch_height, stretch_ascent);
23748 }
23749 }
23750
23751 it->char_to_display = saved_char;
23752 it->position = saved_pos;
23753 it->avoid_cursor_p = saved_avoid_cursor;
23754 it->start_of_box_run_p = saved_box_start;
23755 it->object = save_object;
23756 it->face_id = saved_face_id;
23757 }
23758 if (it->glyph_row->reversed_p)
23759 {
23760
23761
23762
23763
23764
23765 struct font *font = face->font ? face->font : FRAME_FONT (f);
23766 struct glyph *row_start = it->glyph_row->glyphs[TEXT_AREA];
23767 struct glyph *row_end = row_start + it->glyph_row->used[TEXT_AREA];
23768 struct glyph *g;
23769 int row_width, stretch_ascent, stretch_width;
23770 struct text_pos saved_pos;
23771 int saved_face_id;
23772 bool saved_avoid_cursor, saved_box_start;
23773
23774 for (row_width = 0, g = row_start; g < row_end; g++)
23775 row_width += g->pixel_width;
23776
23777
23778
23779
23780 if ((WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
23781 == (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)
23782 || WINDOW_RIGHT_FRINGE_WIDTH (it->w) != 0)
23783 stretch_width = window_box_width (it->w, TEXT_AREA);
23784 else
23785 stretch_width = it->last_visible_x - it->first_visible_x;
23786 stretch_width -= row_width;
23787
23788 if (stretch_width > 0)
23789 {
23790 stretch_ascent =
23791 (((it->ascent + it->descent)
23792 * FONT_BASE (font)) / FONT_HEIGHT (font));
23793 saved_pos = it->position;
23794 clear_position (it);
23795 saved_avoid_cursor = it->avoid_cursor_p;
23796 it->avoid_cursor_p = true;
23797 saved_face_id = it->face_id;
23798 saved_box_start = it->start_of_box_run_p;
23799
23800
23801
23802 it->face_id = (it->glyph_row->ends_at_zv_p ?
23803 default_face->id : face->id);
23804
23805 it->start_of_box_run_p = false;
23806 append_stretch_glyph (it, Qnil, stretch_width,
23807 it->ascent + it->descent, stretch_ascent);
23808 it->position = saved_pos;
23809 it->avoid_cursor_p = saved_avoid_cursor;
23810 it->face_id = saved_face_id;
23811 it->start_of_box_run_p = saved_box_start;
23812 }
23813
23814
23815
23816
23817 if (stretch_width < 0)
23818 it->glyph_row->x = stretch_width;
23819 }
23820 it->face_id = orig_face_id;
23821 }
23822 else
23823 #endif
23824 {
23825
23826 int saved_x = it->current_x;
23827 struct text_pos saved_pos = it->position;
23828 Lisp_Object saved_object = it->object;;
23829 enum display_element_type saved_what = it->what;
23830
23831 it->what = IT_CHARACTER;
23832 clear_position (it);
23833 it->object = Qnil;
23834 it->c = it->char_to_display = ' ';
23835 it->len = 1;
23836
23837 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23838 && (it->glyph_row->used[LEFT_MARGIN_AREA]
23839 < WINDOW_LEFT_MARGIN_WIDTH (it->w))
23840 && !it->glyph_row->mode_line_p
23841 && face->background != FRAME_BACKGROUND_PIXEL (f))
23842 {
23843 struct glyph *g = it->glyph_row->glyphs[LEFT_MARGIN_AREA];
23844 struct glyph *e = g + it->glyph_row->used[LEFT_MARGIN_AREA];
23845
23846 for (it->current_x = 0; g < e; g++)
23847 it->current_x += g->pixel_width;
23848
23849 it->area = LEFT_MARGIN_AREA;
23850 it->face_id = default_face->id;
23851 while (it->glyph_row->used[LEFT_MARGIN_AREA]
23852 < WINDOW_LEFT_MARGIN_WIDTH (it->w)
23853 && g < it->glyph_row->glyphs[TEXT_AREA])
23854 {
23855 PRODUCE_GLYPHS (it);
23856
23857
23858 it->current_x += it->pixel_width;
23859 g++;
23860 }
23861
23862 it->current_x = saved_x;
23863 it->area = TEXT_AREA;
23864 }
23865
23866
23867
23868
23869 it->face_id = (it->glyph_row->ends_at_zv_p ?
23870 default_face->id : face->id);
23871
23872
23873
23874
23875
23876 it->current_x = it->glyph_row->used[TEXT_AREA];
23877
23878
23879
23880
23881
23882
23883
23884
23885 const int indicator_column =
23886 fill_column_indicator_column (it, 1) - it->first_visible_x;
23887
23888
23889 while (it->current_x <= it->last_visible_x)
23890 {
23891 if (it->current_x != indicator_column)
23892 PRODUCE_GLYPHS (it);
23893 else
23894 {
23895 int saved_face_id = it->face_id;
23896 it->face_id
23897 = merge_faces (it->w, Qfill_column_indicator, 0, extend_face_id);
23898 it->c = it->char_to_display
23899 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23900
23901 PRODUCE_GLYPHS (it);
23902
23903 it->face_id = saved_face_id;
23904 it->c = it->char_to_display = ' ';
23905 }
23906 }
23907
23908 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
23909 && (it->glyph_row->used[RIGHT_MARGIN_AREA]
23910 < WINDOW_RIGHT_MARGIN_WIDTH (it->w))
23911 && !it->glyph_row->mode_line_p
23912 && face->background != FRAME_BACKGROUND_PIXEL (f))
23913 {
23914 struct glyph *g = it->glyph_row->glyphs[RIGHT_MARGIN_AREA];
23915 struct glyph *e = g + it->glyph_row->used[RIGHT_MARGIN_AREA];
23916
23917 for ( ; g < e; g++)
23918 it->current_x += g->pixel_width;
23919
23920 it->area = RIGHT_MARGIN_AREA;
23921 it->face_id = default_face->id;
23922 while (it->glyph_row->used[RIGHT_MARGIN_AREA]
23923 < WINDOW_RIGHT_MARGIN_WIDTH (it->w)
23924 && g < it->glyph_row->glyphs[LAST_AREA])
23925 {
23926 PRODUCE_GLYPHS (it);
23927 it->current_x += it->pixel_width;
23928 g++;
23929 }
23930
23931 it->area = TEXT_AREA;
23932 }
23933
23934
23935
23936 it->current_x = saved_x;
23937 it->object = saved_object;
23938 it->position = saved_pos;
23939 it->what = saved_what;
23940 it->face_id = orig_face_id;
23941 }
23942 }
23943
23944
23945
23946
23947
23948 static bool
23949 trailing_whitespace_p (ptrdiff_t charpos)
23950 {
23951 ptrdiff_t bytepos = CHAR_TO_BYTE (charpos);
23952 int c = 0;
23953
23954 while (bytepos < ZV_BYTE
23955 && (c = FETCH_BYTE (bytepos),
23956 c == ' ' || c == '\t'))
23957 ++bytepos;
23958
23959 if (bytepos >= ZV_BYTE || c == '\n' || c == '\r')
23960 {
23961 if (bytepos != PT_BYTE)
23962 return true;
23963 }
23964 return false;
23965 }
23966
23967
23968
23969
23970 static void
23971 highlight_trailing_whitespace (struct it *it)
23972 {
23973 struct glyph_row *row = it->glyph_row;
23974 int used = row->used[TEXT_AREA];
23975
23976 if (used)
23977 {
23978 struct glyph *start = row->glyphs[TEXT_AREA];
23979 struct glyph *glyph = start + used - 1;
23980
23981 if (row->reversed_p)
23982 {
23983
23984
23985 glyph = start;
23986 start = row->glyphs[TEXT_AREA] + used - 1;
23987 }
23988
23989
23990
23991
23992
23993 if (!row->reversed_p)
23994 {
23995 while (glyph >= start
23996 && (glyph->type == CHAR_GLYPH
23997 || glyph->type == STRETCH_GLYPH)
23998 && NILP (glyph->object))
23999 --glyph;
24000 }
24001 else
24002 {
24003 while (glyph <= start
24004 && (glyph->type == CHAR_GLYPH || glyph->type == STRETCH_GLYPH)
24005 && NILP (glyph->object))
24006 ++glyph;
24007 }
24008
24009
24010
24011
24012 if ((row->reversed_p ? glyph <= start : glyph >= start)
24013 && BUFFERP (glyph->object)
24014 && (glyph->type == STRETCH_GLYPH
24015 || (glyph->type == CHAR_GLYPH
24016 && glyph->u.ch == ' '))
24017 && trailing_whitespace_p (glyph->charpos))
24018 {
24019 int face_id = lookup_named_face (it->w, it->f, Qtrailing_whitespace, false);
24020 if (face_id < 0)
24021 return;
24022
24023 if (!row->reversed_p)
24024 {
24025 while (glyph >= start
24026 && BUFFERP (glyph->object)
24027 && (glyph->type == STRETCH_GLYPH
24028 || (glyph->type == CHAR_GLYPH
24029 && glyph->u.ch == ' ')))
24030 (glyph--)->face_id = face_id;
24031 }
24032 else
24033 {
24034 while (glyph <= start
24035 && BUFFERP (glyph->object)
24036 && (glyph->type == STRETCH_GLYPH
24037 || (glyph->type == CHAR_GLYPH
24038 && glyph->u.ch == ' ')))
24039 (glyph++)->face_id = face_id;
24040 }
24041 }
24042 }
24043 }
24044
24045
24046
24047
24048
24049 static bool
24050 row_for_charpos_p (struct glyph_row *row, ptrdiff_t charpos)
24051 {
24052 bool result = true;
24053
24054 if (charpos == CHARPOS (row->end.pos)
24055 || charpos == MATRIX_ROW_END_CHARPOS (row))
24056 {
24057
24058
24059
24060
24061
24062
24063
24064
24065 if (CHARPOS (row->end.string_pos) >= 0)
24066 {
24067 if (row->continued_p)
24068 result = true;
24069 else
24070 {
24071
24072 struct glyph *beg = row->glyphs[TEXT_AREA];
24073 struct glyph *end = beg + row->used[TEXT_AREA] - 1;
24074 struct glyph *glyph;
24075
24076 result = false;
24077 for (glyph = end; glyph >= beg; --glyph)
24078 if (STRINGP (glyph->object))
24079 {
24080 Lisp_Object prop
24081 = Fget_char_property (make_fixnum (charpos),
24082 Qdisplay, Qnil);
24083 result =
24084 (!NILP (prop)
24085 && display_prop_string_p (prop, glyph->object));
24086
24087
24088
24089 if (!result)
24090 {
24091 Lisp_Object s = glyph->object;
24092
24093 for ( ; glyph >= beg && EQ (glyph->object, s); --glyph)
24094 {
24095 ptrdiff_t gpos = glyph->charpos;
24096
24097 if (!NILP (Fget_char_property (make_fixnum (gpos),
24098 Qcursor, s)))
24099 {
24100 result = true;
24101 break;
24102 }
24103 }
24104 }
24105 break;
24106 }
24107 }
24108 }
24109 else if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
24110 {
24111
24112
24113
24114
24115 if (!row->ends_in_ellipsis_p)
24116 result = row->continued_p;
24117 else
24118
24119
24120
24121
24122 result = false;
24123 }
24124
24125
24126 else
24127 result = row->ends_at_zv_p;
24128 }
24129
24130 return result;
24131 }
24132
24133
24134
24135
24136 static bool
24137 cursor_row_p (struct glyph_row *row)
24138 {
24139 return row_for_charpos_p (row, PT);
24140 }
24141
24142
24143
24144
24145
24146
24147
24148
24149 static bool
24150 push_prefix_prop (struct it *it, Lisp_Object prop)
24151 {
24152 struct text_pos pos =
24153 STRINGP (it->string) ? it->current.string_pos : it->current.pos;
24154
24155 eassert (it->method == GET_FROM_BUFFER
24156 || it->method == GET_FROM_DISPLAY_VECTOR
24157 || it->method == GET_FROM_STRING
24158 || it->method == GET_FROM_IMAGE);
24159
24160
24161
24162
24163
24164 push_it (it, &pos);
24165
24166 if (STRINGP (prop))
24167 {
24168 if (SCHARS (prop) == 0)
24169 {
24170 pop_it (it);
24171 return false;
24172 }
24173
24174 it->string = prop;
24175 it->string_from_prefix_prop_p = true;
24176 it->multibyte_p = STRING_MULTIBYTE (it->string);
24177 it->current.overlay_string_index = -1;
24178 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
24179 it->end_charpos = it->string_nchars = SCHARS (it->string);
24180 it->method = GET_FROM_STRING;
24181 it->stop_charpos = 0;
24182 it->prev_stop = 0;
24183 it->base_level_stop = 0;
24184 it->cmp_it.id = -1;
24185
24186
24187
24188 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
24189 it->paragraph_embedding = it->bidi_it.paragraph_dir;
24190 else
24191 it->paragraph_embedding = L2R;
24192
24193
24194 if (it->bidi_p)
24195 {
24196 it->bidi_it.string.lstring = it->string;
24197 it->bidi_it.string.s = NULL;
24198 it->bidi_it.string.schars = it->end_charpos;
24199 it->bidi_it.string.bufpos = IT_CHARPOS (*it);
24200 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
24201 it->bidi_it.string.unibyte = !it->multibyte_p;
24202 it->bidi_it.w = it->w;
24203 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
24204 }
24205 }
24206 else if (CONSP (prop) && EQ (XCAR (prop), Qspace))
24207 {
24208 it->method = GET_FROM_STRETCH;
24209 it->object = prop;
24210 }
24211 #ifdef HAVE_WINDOW_SYSTEM
24212 else if (IMAGEP (prop))
24213 {
24214 it->what = IT_IMAGE;
24215 it->image_id = lookup_image (it->f, prop, it->face_id);
24216 it->method = GET_FROM_IMAGE;
24217 }
24218 #endif
24219 else
24220 {
24221 pop_it (it);
24222 return false;
24223 }
24224
24225 return true;
24226 }
24227
24228
24229
24230 static Lisp_Object
24231 get_it_property (struct it *it, Lisp_Object prop)
24232 {
24233 Lisp_Object position, object = it->object;
24234
24235 if (STRINGP (object))
24236 position = make_fixnum (IT_STRING_CHARPOS (*it));
24237 else if (BUFFERP (object))
24238 {
24239 position = make_fixnum (IT_CHARPOS (*it));
24240 object = it->window;
24241 }
24242 else
24243 return Qnil;
24244
24245 return Fget_char_property (position, prop, object);
24246 }
24247
24248
24249
24250
24251 static Lisp_Object
24252 get_line_prefix_it_property (struct it *it, Lisp_Object prop)
24253 {
24254 Lisp_Object prefix = get_it_property (it, prop);
24255
24256
24257
24258 if (NILP (prefix) && it->sp > 0 && STRINGP (it->object))
24259 return Fget_char_property (make_fixnum (IT_CHARPOS (*it)), prop,
24260 it->w->contents);
24261 return prefix;
24262 }
24263
24264
24265
24266 static void
24267 handle_line_prefix (struct it *it)
24268 {
24269 Lisp_Object prefix;
24270
24271 if (it->continuation_lines_width > 0)
24272 {
24273 prefix = get_line_prefix_it_property (it, Qwrap_prefix);
24274 if (NILP (prefix))
24275 prefix = Vwrap_prefix;
24276 }
24277 else
24278 {
24279 prefix = get_line_prefix_it_property (it, Qline_prefix);
24280 if (NILP (prefix))
24281 prefix = Vline_prefix;
24282 }
24283 if (! NILP (prefix) && push_prefix_prop (it, prefix))
24284 {
24285
24286
24287
24288 it->line_wrap = TRUNCATE;
24289 it->avoid_cursor_p = true;
24290 }
24291 }
24292
24293
24294
24295
24296
24297
24298
24299 static void
24300 unproduce_glyphs (struct it *it, int n)
24301 {
24302 struct glyph *glyph, *end;
24303
24304 eassert (it->glyph_row);
24305 eassert (it->glyph_row->reversed_p);
24306 eassert (it->area == TEXT_AREA);
24307 eassert (n <= it->glyph_row->used[TEXT_AREA]);
24308
24309 if (n > it->glyph_row->used[TEXT_AREA])
24310 n = it->glyph_row->used[TEXT_AREA];
24311 glyph = it->glyph_row->glyphs[TEXT_AREA] + n;
24312 end = it->glyph_row->glyphs[TEXT_AREA] + it->glyph_row->used[TEXT_AREA];
24313 for ( ; glyph < end; glyph++)
24314 glyph[-n] = *glyph;
24315 }
24316
24317
24318
24319 static void
24320 find_row_edges (struct it *it, struct glyph_row *row,
24321 ptrdiff_t min_pos, ptrdiff_t min_bpos,
24322 ptrdiff_t max_pos, ptrdiff_t max_bpos)
24323 {
24324
24325
24326
24327
24328
24329 if (min_pos <= ZV && min_pos < row->start.pos.charpos)
24330 SET_TEXT_POS (row->minpos, min_pos, min_bpos);
24331 else
24332
24333
24334
24335 row->minpos = row->start.pos;
24336 if (max_pos <= 0)
24337 {
24338 max_pos = CHARPOS (it->current.pos);
24339 max_bpos = BYTEPOS (it->current.pos);
24340 }
24341
24342
24343
24344
24345
24346
24347
24348
24349
24350
24351
24352
24353
24354
24355
24356
24357
24358 if (row->ends_at_zv_p)
24359 row->maxpos = it->current.pos;
24360 else if (row->used[TEXT_AREA])
24361 {
24362 bool seen_this_string = false;
24363 struct glyph_row *r1 = row - 1;
24364
24365
24366 if (STRINGP (it->object)
24367
24368 && row > it->w->desired_matrix->rows
24369
24370 && !r1->mode_line_p
24371
24372 && r1->ends_in_newline_from_string_p)
24373 {
24374 struct glyph *start, *end;
24375
24376
24377
24378
24379
24380 if (!r1->reversed_p)
24381 {
24382 start = r1->glyphs[TEXT_AREA];
24383 end = start + r1->used[TEXT_AREA];
24384
24385 while (end > start
24386 && NILP ((end - 1)->object)
24387 && (end - 1)->charpos <= 0)
24388 --end;
24389 if (end > start)
24390 {
24391 if (EQ ((end - 1)->object, it->object))
24392 seen_this_string = true;
24393 }
24394 else
24395
24396
24397
24398
24399
24400 seen_this_string = true;
24401 }
24402 else
24403 {
24404 end = r1->glyphs[TEXT_AREA] - 1;
24405 start = end + r1->used[TEXT_AREA];
24406 while (end < start
24407 && NILP ((end + 1)->object)
24408 && (end + 1)->charpos <= 0)
24409 ++end;
24410 if (end < start)
24411 {
24412 if (EQ ((end + 1)->object, it->object))
24413 seen_this_string = true;
24414 }
24415 else
24416 seen_this_string = true;
24417 }
24418 }
24419
24420
24421
24422 if (row->ends_in_newline_from_string_p && !seen_this_string)
24423 {
24424
24425
24426
24427
24428
24429
24430
24431
24432 if (CHARPOS (row->end.pos) > max_pos)
24433 inc_both (&max_pos, &max_bpos);
24434 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24435 }
24436 else if (CHARPOS (it->eol_pos) > 0)
24437 SET_TEXT_POS (row->maxpos,
24438 CHARPOS (it->eol_pos) + 1, BYTEPOS (it->eol_pos) + 1);
24439 else if (row->continued_p)
24440 {
24441
24442
24443
24444
24445
24446
24447 if (IT_CHARPOS (*it) == max_pos && it->method != GET_FROM_BUFFER)
24448 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24449 else
24450 {
24451 inc_both (&max_pos, &max_bpos);
24452 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24453 }
24454 }
24455 else if (row->truncated_on_right_p)
24456
24457
24458
24459 row->maxpos = it->current.pos;
24460 else if (max_pos == min_pos && it->method != GET_FROM_BUFFER)
24461
24462 row->maxpos = row->minpos;
24463 else
24464 emacs_abort ();
24465 }
24466 else
24467 row->maxpos = it->current.pos;
24468 }
24469
24470
24471
24472 static ptrdiff_t
24473 display_count_lines_logically (ptrdiff_t start_byte, ptrdiff_t limit_byte,
24474 ptrdiff_t count, ptrdiff_t *byte_pos_ptr)
24475 {
24476 if (!display_line_numbers_widen || (BEGV == BEG && ZV == Z))
24477 return display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
24478
24479 ptrdiff_t val;
24480 specpdl_ref pdl_count = SPECPDL_INDEX ();
24481 record_unwind_protect (save_restriction_restore, save_restriction_save ());
24482 labeled_restrictions_remove_in_current_buffer ();
24483 Fwiden ();
24484 val = display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
24485 unbind_to (pdl_count, Qnil);
24486 return val;
24487 }
24488
24489
24490
24491 static ptrdiff_t
24492 display_count_lines_visually (struct it *it)
24493 {
24494 struct it tem_it;
24495 ptrdiff_t to;
24496 struct text_pos from;
24497
24498
24499
24500
24501
24502
24503 if (it->lnum_bytepos > 0)
24504 return it->lnum + 1;
24505 else
24506 {
24507 specpdl_ref count = SPECPDL_INDEX ();
24508
24509 if (IT_CHARPOS (*it) <= PT)
24510 {
24511 from = it->current.pos;
24512 to = PT;
24513 }
24514 else
24515 {
24516 SET_TEXT_POS (from, PT, PT_BYTE);
24517 to = IT_CHARPOS (*it);
24518 }
24519
24520
24521
24522 specbind (Qdisplay_line_numbers, Qrelative);
24523 start_display (&tem_it, it->w, from);
24524
24525
24526
24527
24528 move_it_to (&tem_it, to, -1,
24529 tem_it.last_visible_y
24530 + (SCROLL_LIMIT + 10) * FRAME_LINE_HEIGHT (tem_it.f),
24531 -1, MOVE_TO_POS | MOVE_TO_Y);
24532 unbind_to (count, Qnil);
24533 return IT_CHARPOS (*it) <= PT ? -tem_it.vpos : tem_it.vpos;
24534 }
24535 }
24536
24537
24538
24539
24540 static void
24541 maybe_produce_line_number (struct it *it)
24542 {
24543 ptrdiff_t last_line = it->lnum;
24544 ptrdiff_t start_from, bytepos;
24545 ptrdiff_t this_line;
24546 bool first_time = false;
24547 ptrdiff_t beg_byte;
24548 ptrdiff_t z_byte;
24549 bool line_numbers_wide;
24550 void *itdata = bidi_shelve_cache ();
24551
24552 if (display_line_numbers_offset
24553 && !display_line_numbers_widen
24554 && !EQ (Vdisplay_line_numbers, Qvisual)
24555 && !EQ (Vdisplay_line_numbers, Qrelative))
24556 line_numbers_wide = true;
24557 else
24558 line_numbers_wide = display_line_numbers_widen;
24559
24560 beg_byte = line_numbers_wide ? BEG_BYTE : BEGV_BYTE;
24561 z_byte = line_numbers_wide ? Z_BYTE : ZV_BYTE;
24562
24563 if (EQ (Vdisplay_line_numbers, Qvisual))
24564 this_line = display_count_lines_visually (it);
24565 else
24566 {
24567 if (!last_line)
24568 {
24569
24570 if (it->w->base_line_number > 0
24571 && it->w->base_line_pos > 0
24572 && it->w->base_line_pos <= IT_CHARPOS (*it)
24573
24574
24575
24576
24577 && !(line_numbers_wide
24578 && (BEG_BYTE != BEGV_BYTE || Z_BYTE != ZV_BYTE))
24579 && !current_buffer->clip_changed)
24580 {
24581 start_from = CHAR_TO_BYTE (it->w->base_line_pos);
24582 last_line = it->w->base_line_number - 1;
24583 }
24584 else
24585 start_from = beg_byte;
24586 if (!it->lnum_bytepos)
24587 first_time = true;
24588 }
24589 else
24590 start_from = it->lnum_bytepos;
24591
24592
24593
24594
24595 if (!(beg_byte <= start_from && start_from <= z_byte))
24596 {
24597 last_line = 0;
24598 start_from = beg_byte;
24599 }
24600
24601 this_line =
24602 last_line + display_count_lines_logically (start_from,
24603 IT_BYTEPOS (*it),
24604 IT_CHARPOS (*it), &bytepos);
24605 eassert (this_line > 0 || (this_line == 0 && start_from == beg_byte));
24606 eassert (bytepos == IT_BYTEPOS (*it));
24607 }
24608
24609
24610 if (this_line != last_line || !it->lnum_bytepos)
24611 {
24612 it->lnum = this_line;
24613 it->lnum_bytepos = IT_BYTEPOS (*it);
24614 }
24615
24616
24617 struct it tem_it;
24618 char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1];
24619 bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false;
24620 ptrdiff_t lnum_offset = -1;
24621 int lnum_face_id = merge_faces (it->w, Qline_number, 0, DEFAULT_FACE_ID);
24622 int current_lnum_face_id
24623 = merge_faces (it->w, Qline_number_current_line, 0, DEFAULT_FACE_ID);
24624
24625
24626 bool save_free_realized_faces = inhibit_free_realized_faces;
24627 inhibit_free_realized_faces = true;
24628
24629 if ((EQ (Vdisplay_line_numbers, Qrelative)
24630 || EQ (Vdisplay_line_numbers, Qvisual)
24631 || lnum_face_id != current_lnum_face_id)
24632 && !it->pt_lnum)
24633 {
24634 ptrdiff_t ignored;
24635 if (PT_BYTE > it->lnum_bytepos && !EQ (Vdisplay_line_numbers, Qvisual))
24636 it->pt_lnum =
24637 this_line + display_count_lines_logically (it->lnum_bytepos, PT_BYTE,
24638 PT, &ignored);
24639 else
24640 it->pt_lnum = display_count_lines_logically (beg_byte, PT_BYTE, PT,
24641 &ignored);
24642 }
24643
24644 if (!it->lnum_width)
24645 {
24646 if (FIXNATP (Vdisplay_line_numbers_width))
24647 it->lnum_width = XFIXNAT (Vdisplay_line_numbers_width);
24648
24649
24650
24651 ptrdiff_t max_lnum;
24652
24653 if (NILP (Vdisplay_line_numbers_current_absolute)
24654 && (EQ (Vdisplay_line_numbers, Qrelative)
24655 || EQ (Vdisplay_line_numbers, Qvisual)))
24656
24657
24658 max_lnum = it->w->desired_matrix->nrows - 2;
24659 else if (EQ (Vdisplay_line_numbers, Qvisual))
24660 max_lnum = it->pt_lnum + it->w->desired_matrix->nrows - 1;
24661 else
24662 max_lnum = this_line + it->w->desired_matrix->nrows - 1 - it->vpos;
24663 max_lnum = max (1, max_lnum);
24664 it->lnum_width = max (it->lnum_width, log10 (max_lnum) + 1);
24665 eassert (it->lnum_width > 0);
24666 }
24667 if (EQ (Vdisplay_line_numbers, Qrelative))
24668 lnum_offset = it->pt_lnum;
24669 else if (EQ (Vdisplay_line_numbers, Qvisual))
24670 lnum_offset = 0;
24671 else if (display_line_numbers_offset)
24672 lnum_offset -= display_line_numbers_offset;
24673
24674
24675
24676 ptrdiff_t lnum_to_display = eabs (this_line - lnum_offset);
24677 if ((EQ (Vdisplay_line_numbers, Qrelative)
24678 || EQ (Vdisplay_line_numbers, Qvisual))
24679 && lnum_to_display == 0
24680 && !NILP (Vdisplay_line_numbers_current_absolute))
24681 lnum_to_display = it->pt_lnum + 1;
24682
24683
24684
24685
24686
24687 pint2str (lnum_buf, it->lnum_width + 1, lnum_to_display);
24688 strcat (lnum_buf, " ");
24689
24690
24691 init_iterator (&tem_it, it->w, -1, -1, &scratch_glyph_row,
24692
24693 DEFAULT_FACE_ID);
24694 scratch_glyph_row.reversed_p = false;
24695 scratch_glyph_row.used[TEXT_AREA] = 0;
24696 SET_TEXT_POS (tem_it.position, 0, 0);
24697 tem_it.avoid_cursor_p = true;
24698 tem_it.bidi_p = true;
24699 tem_it.bidi_it.type = WEAK_EN;
24700
24701
24702
24703 tem_it.bidi_it.resolved_level = 2;
24704
24705
24706
24707 int width_limit =
24708 tem_it.last_visible_x - tem_it.first_visible_x
24709 - 3 * FRAME_COLUMN_WIDTH (it->f);
24710
24711 tem_it.face_id = lnum_face_id;
24712
24713
24714 if (lnum_face_id != current_lnum_face_id
24715 && (EQ (Vdisplay_line_numbers, Qvisual)
24716 ? this_line == 0
24717 : this_line == it->pt_lnum)
24718 && it->what != IT_EOB)
24719 tem_it.face_id = current_lnum_face_id;
24720 else if (!beyond_zv)
24721 {
24722 if (display_line_numbers_major_tick > 0
24723 && (lnum_to_display % display_line_numbers_major_tick == 0))
24724 tem_it.face_id = merge_faces (it->w, Qline_number_major_tick,
24725 0, DEFAULT_FACE_ID);
24726 else if (display_line_numbers_minor_tick > 0
24727 && (lnum_to_display % display_line_numbers_minor_tick == 0))
24728 tem_it.face_id = merge_faces (it->w, Qline_number_minor_tick,
24729 0, DEFAULT_FACE_ID);
24730 }
24731
24732
24733 for (const char *p = lnum_buf; *p; p++)
24734 {
24735
24736
24737 if (beyond_zv
24738
24739 || (!EQ (Vdisplay_line_numbers, Qvisual)
24740 && (it->continuation_lines_width > 0
24741 || (this_line == last_line && !first_time))))
24742 tem_it.c = tem_it.char_to_display = ' ';
24743 else
24744 tem_it.c = tem_it.char_to_display = *p;
24745 tem_it.len = 1;
24746
24747 SET_TEXT_POS (tem_it.position, -1, -1);
24748 PRODUCE_GLYPHS (&tem_it);
24749
24750
24751
24752 if (tem_it.current_x >= width_limit)
24753 {
24754 it->lnum_width = 0;
24755 it->lnum_pixel_width = 0;
24756 bidi_unshelve_cache (itdata, false);
24757 inhibit_free_realized_faces = save_free_realized_faces;
24758 return;
24759 }
24760 }
24761
24762 inhibit_free_realized_faces = save_free_realized_faces;
24763
24764
24765 it->lnum_pixel_width = tem_it.current_x;
24766
24767 struct glyph *g = scratch_glyph_row.glyphs[TEXT_AREA];
24768 struct glyph *e = g + scratch_glyph_row.used[TEXT_AREA];
24769 struct glyph *p = it->glyph_row ? it->glyph_row->glyphs[TEXT_AREA] : NULL;
24770 short *u = it->glyph_row ? &it->glyph_row->used[TEXT_AREA] : NULL;
24771
24772 eassert (it->glyph_row == NULL || it->glyph_row->used[TEXT_AREA] == 0);
24773
24774 for ( ; g < e; g++)
24775 {
24776 it->current_x += g->pixel_width;
24777
24778
24779
24780 if (it->current_x > it->first_visible_x)
24781 it->hpos++;
24782 if (p)
24783 {
24784 *p++ = *g;
24785 (*u)++;
24786 }
24787 }
24788
24789
24790
24791
24792 if (!beyond_zv)
24793 {
24794 if (it->glyph_row)
24795 {
24796 struct glyph_row *row = it->glyph_row;
24797
24798 it->max_ascent = max (row->ascent, tem_it.max_ascent);
24799 it->max_descent = max (row->height - row->ascent, tem_it.max_descent);
24800 it->max_phys_ascent = max (row->phys_ascent, tem_it.max_phys_ascent);
24801 it->max_phys_descent = max (row->phys_height - row->phys_ascent,
24802 tem_it.max_phys_descent);
24803 }
24804 else
24805 {
24806 it->max_ascent = max (it->max_ascent, tem_it.max_ascent);
24807 it->max_descent = max (it->max_descent, tem_it.max_descent);
24808 it->max_phys_ascent = max (it->max_phys_ascent,
24809 tem_it.max_phys_ascent);
24810 it->max_phys_descent = max (it->max_phys_descent,
24811 tem_it.max_phys_descent);
24812 }
24813 }
24814
24815 it->line_number_produced_p = true;
24816
24817 bidi_unshelve_cache (itdata, false);
24818 }
24819
24820
24821
24822 static bool
24823 should_produce_line_number (struct it *it)
24824 {
24825 if (NILP (Vdisplay_line_numbers))
24826 return false;
24827
24828
24829 if (MINI_WINDOW_P (it->w))
24830 return false;
24831
24832 #ifdef HAVE_WINDOW_SYSTEM
24833
24834 if (FRAME_TOOLTIP_P (XFRAME (WINDOW_FRAME (it->w))))
24835 return false;
24836 #endif
24837
24838
24839
24840
24841
24842 Lisp_Object val = Fget_char_property (make_fixnum (IT_CHARPOS (*it)),
24843 Qdisplay_line_numbers_disable,
24844 it->window);
24845
24846
24847
24848 if (NILP (val) && IT_CHARPOS (*it) >= ZV)
24849 val = disable_line_numbers_overlay_at_eob ();
24850 return NILP (val) ? true : false;
24851 }
24852
24853
24854
24855
24856
24857 static bool
24858 row_text_area_empty (struct glyph_row *row)
24859 {
24860 if (!row->reversed_p)
24861 {
24862 for (struct glyph *g = row->glyphs[TEXT_AREA];
24863 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
24864 g++)
24865 if (!NILP (g->object) || g->charpos > 0)
24866 return false;
24867 }
24868 else
24869 {
24870 for (struct glyph *g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
24871 g > row->glyphs[TEXT_AREA];
24872 g--)
24873 if (!NILP ((g - 1)->object) || (g - 1)->charpos > 0)
24874 return false;
24875 }
24876
24877 return true;
24878 }
24879
24880
24881
24882
24883
24884
24885
24886
24887 static bool
24888 display_line (struct it *it, int cursor_vpos)
24889 {
24890 struct glyph_row *row = it->glyph_row;
24891 Lisp_Object overlay_arrow_string;
24892 struct it wrap_it;
24893 void *wrap_data = NULL;
24894 bool may_wrap = false;
24895 int wrap_x UNINIT;
24896 int wrap_row_used = -1;
24897 int wrap_row_ascent UNINIT, wrap_row_height UNINIT;
24898 int wrap_row_phys_ascent UNINIT, wrap_row_phys_height UNINIT;
24899 int wrap_row_extra_line_spacing UNINIT;
24900 ptrdiff_t wrap_row_min_pos UNINIT, wrap_row_min_bpos UNINIT;
24901 ptrdiff_t wrap_row_max_pos UNINIT, wrap_row_max_bpos UNINIT;
24902 int cvpos;
24903 ptrdiff_t min_pos = ZV + 1, max_pos = 0;
24904 ptrdiff_t min_bpos UNINIT, max_bpos UNINIT;
24905 bool pending_handle_line_prefix = false;
24906 int tab_line = window_wants_tab_line (it->w);
24907 int header_line = window_wants_header_line (it->w);
24908 bool hscroll_this_line = (cursor_vpos >= 0
24909 && it->vpos == cursor_vpos - tab_line - header_line
24910 && hscrolling_current_line_p (it->w));
24911 int first_visible_x = it->first_visible_x;
24912 int last_visible_x = it->last_visible_x;
24913 int x_incr = 0;
24914
24915
24916 eassert (it->hpos == 0 && it->current_x == 0);
24917
24918 if (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
24919 >= it->w->desired_matrix->nrows)
24920 {
24921 it->w->nrows_scale_factor++;
24922 it->f->fonts_changed = true;
24923 return false;
24924 }
24925
24926
24927 prepare_desired_row (it->w, row, false);
24928
24929 row->y = it->current_y;
24930 row->start = it->start;
24931 row->continuation_lines_width = it->continuation_lines_width;
24932 row->displays_text_p = true;
24933 row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p;
24934 it->starts_in_middle_of_char_p = false;
24935 it->stretch_adjust = 0;
24936 it->line_number_produced_p = false;
24937
24938
24939
24940
24941 if (hscroll_this_line)
24942 x_incr =
24943 (window_hscroll_limited (it->w, it->f) - it->w->min_hscroll)
24944 * FRAME_COLUMN_WIDTH (it->f);
24945
24946 bool line_number_needed = should_produce_line_number (it);
24947
24948
24949
24950
24951 if (it->current_x < it->first_visible_x + x_incr)
24952 {
24953 enum move_it_result move_result;
24954
24955 this_line_min_pos = row->start.pos;
24956 if (hscroll_this_line)
24957 {
24958 it->first_visible_x += x_incr;
24959 it->last_visible_x += x_incr;
24960 }
24961 if (current_buffer->long_line_optimizations_p
24962 && it->line_wrap == TRUNCATE
24963 && window_hscroll_limited (it->w, it->f) > large_hscroll_threshold)
24964 {
24965
24966
24967
24968
24969 ptrdiff_t chars_to_skip =
24970 it->first_visible_x / FRAME_COLUMN_WIDTH (it->f);
24971 move_result = fast_move_it_horizontally (it, chars_to_skip);
24972
24973 if (move_result == MOVE_X_REACHED)
24974 it->current_x = it->first_visible_x;
24975 else
24976 it->current_x = it->first_visible_x - FRAME_COLUMN_WIDTH (it->f);
24977 }
24978 else
24979 move_result = move_it_in_display_line_to (it, ZV, it->first_visible_x,
24980 MOVE_TO_POS | MOVE_TO_X);
24981
24982
24983
24984
24985
24986
24987 if (it->current_x < it->first_visible_x
24988 && (move_result == MOVE_NEWLINE_OR_CR
24989 || move_result == MOVE_POS_MATCH_OR_ZV))
24990 it->current_x = it->first_visible_x;
24991
24992
24993
24994 it->line_number_produced_p = false;
24995
24996
24997
24998
24999
25000
25001
25002
25003 min_pos = CHARPOS (this_line_min_pos);
25004 min_bpos = BYTEPOS (this_line_min_pos);
25005
25006
25007 if (line_number_needed)
25008 maybe_produce_line_number (it);
25009 }
25010 else if (it->area == TEXT_AREA)
25011 {
25012
25013 if (line_number_needed)
25014 maybe_produce_line_number (it);
25015
25016
25017
25018 handle_line_prefix (it);
25019 }
25020 else
25021 {
25022
25023
25024
25025
25026
25027
25028
25029 pending_handle_line_prefix = true;
25030 }
25031
25032
25033
25034 row->ascent = it->max_ascent;
25035 row->height = it->max_ascent + it->max_descent;
25036 row->phys_ascent = it->max_phys_ascent;
25037 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
25038 row->extra_line_spacing = it->max_extra_line_spacing;
25039
25040
25041 #define RECORD_MAX_MIN_POS(IT) \
25042 do \
25043 { \
25044 bool composition_p \
25045 = !STRINGP ((IT)->string) && ((IT)->what == IT_COMPOSITION); \
25046 ptrdiff_t current_pos = \
25047 composition_p ? (IT)->cmp_it.charpos \
25048 : IT_CHARPOS (*(IT)); \
25049 ptrdiff_t current_bpos = \
25050 composition_p ? CHAR_TO_BYTE (current_pos) \
25051 : IT_BYTEPOS (*(IT)); \
25052 if (current_pos < min_pos) \
25053 { \
25054 min_pos = current_pos; \
25055 min_bpos = current_bpos; \
25056 } \
25057 if (IT_CHARPOS (*it) > max_pos) \
25058 { \
25059 max_pos = IT_CHARPOS (*it); \
25060 max_bpos = IT_BYTEPOS (*it); \
25061 } \
25062 } \
25063 while (false)
25064
25065
25066
25067 while (true)
25068 {
25069 int n_glyphs_before, hpos_before, x_before;
25070 int x, nglyphs;
25071 int ascent = 0, descent = 0, phys_ascent = 0, phys_descent = 0;
25072
25073
25074
25075 if (!get_next_display_element (it))
25076 {
25077 bool row_has_glyphs = false;
25078
25079
25080
25081
25082 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25083 row->exact_window_width_line_p = true;
25084 else if ((append_space_for_newline (it, true)
25085 && row->used[TEXT_AREA] == 1)
25086 || row->used[TEXT_AREA] == 0
25087 || (row_has_glyphs = row_text_area_empty (row)))
25088 {
25089 row->glyphs[TEXT_AREA]->charpos = -1;
25090
25091
25092 if (!row_has_glyphs)
25093 row->displays_text_p = false;
25094
25095 if (!NILP (BVAR (XBUFFER (it->w->contents), indicate_empty_lines))
25096 && (!MINI_WINDOW_P (it->w)))
25097 row->indicate_empty_line_p = true;
25098 }
25099
25100 it->continuation_lines_width = 0;
25101
25102
25103
25104
25105 it->font_height = Qnil;
25106 it->voffset = 0;
25107 row->ends_at_zv_p = true;
25108
25109
25110
25111
25112
25113
25114
25115
25116 if (row->reversed_p
25117 || lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
25118 != DEFAULT_FACE_ID)
25119 extend_face_to_end_of_line (it);
25120 break;
25121 }
25122
25123
25124
25125 n_glyphs_before = row->used[TEXT_AREA];
25126 x = it->current_x;
25127
25128
25129
25130 if (it->line_wrap != TRUNCATE)
25131 {
25132 ascent = it->max_ascent;
25133 descent = it->max_descent;
25134 phys_ascent = it->max_phys_ascent;
25135 phys_descent = it->max_phys_descent;
25136
25137 if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
25138 {
25139 bool next_may_wrap = may_wrap;
25140
25141 if (char_can_wrap_after (it))
25142 next_may_wrap = true;
25143 else
25144 next_may_wrap = false;
25145
25146 if (may_wrap && char_can_wrap_before (it))
25147 {
25148 SAVE_IT (wrap_it, *it, wrap_data);
25149 wrap_x = x;
25150 wrap_row_used = row->used[TEXT_AREA];
25151 wrap_row_ascent = row->ascent;
25152 wrap_row_height = row->height;
25153 wrap_row_phys_ascent = row->phys_ascent;
25154 wrap_row_phys_height = row->phys_height;
25155 wrap_row_extra_line_spacing = row->extra_line_spacing;
25156 wrap_row_min_pos = min_pos;
25157 wrap_row_min_bpos = min_bpos;
25158 wrap_row_max_pos = max_pos;
25159 wrap_row_max_bpos = max_bpos;
25160 }
25161
25162 may_wrap = next_may_wrap;
25163 }
25164 }
25165
25166 PRODUCE_GLYPHS (it);
25167
25168
25169
25170 if (it->area != TEXT_AREA)
25171 {
25172 row->ascent = max (row->ascent, it->max_ascent);
25173 row->height = max (row->height, it->max_ascent + it->max_descent);
25174 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25175 row->phys_height = max (row->phys_height,
25176 it->max_phys_ascent + it->max_phys_descent);
25177 row->extra_line_spacing = max (row->extra_line_spacing,
25178 it->max_extra_line_spacing);
25179 set_iterator_to_next (it, true);
25180
25181
25182
25183 if (it->area == TEXT_AREA && pending_handle_line_prefix)
25184 {
25185
25186 if (line_number_needed)
25187 maybe_produce_line_number (it);
25188
25189 pending_handle_line_prefix = false;
25190 handle_line_prefix (it);
25191 }
25192 continue;
25193 }
25194
25195
25196
25197
25198
25199
25200
25201
25202
25203
25204 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
25205 hpos_before = it->hpos;
25206 x_before = x;
25207
25208 if (
25209 nglyphs > 0
25210
25211 && it->current_x < it->last_visible_x)
25212 {
25213 it->hpos += nglyphs;
25214 row->ascent = max (row->ascent, it->max_ascent);
25215 row->height = max (row->height, it->max_ascent + it->max_descent);
25216 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25217 row->phys_height = max (row->phys_height,
25218 it->max_phys_ascent + it->max_phys_descent);
25219 row->extra_line_spacing = max (row->extra_line_spacing,
25220 it->max_extra_line_spacing);
25221 if (it->current_x - it->pixel_width < it->first_visible_x
25222
25223
25224
25225 && !line_number_needed
25226
25227
25228
25229
25230 && !row->reversed_p)
25231 row->x = x - it->first_visible_x;
25232
25233
25234 if (it->bidi_p)
25235 RECORD_MAX_MIN_POS (it);
25236 }
25237 else
25238 {
25239 int i, new_x;
25240 struct glyph *glyph;
25241
25242 for (i = 0; i < nglyphs; ++i, x = new_x)
25243 {
25244
25245
25246
25247 if (!row->reversed_p)
25248 glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
25249 else
25250 glyph = row->glyphs[TEXT_AREA] + nglyphs - 1 - i;
25251 new_x = x + glyph->pixel_width;
25252
25253 if (
25254 it->line_wrap != TRUNCATE
25255 && (
25256 new_x > it->last_visible_x
25257
25258 || (new_x == it->last_visible_x
25259 && FRAME_WINDOW_P (it->f)
25260 && (row->reversed_p
25261 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25262 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
25263 {
25264
25265
25266 if (it->hpos == 0
25267 || (new_x == it->last_visible_x
25268 && FRAME_WINDOW_P (it->f)
25269 && (row->reversed_p
25270 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25271 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))
25272 {
25273
25274
25275
25276
25277 row->continued_p = true;
25278 it->current_x = new_x;
25279 it->continuation_lines_width += new_x;
25280 ++it->hpos;
25281 if (i == nglyphs - 1)
25282 {
25283
25284
25285 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
25286 && wrap_row_used > 0
25287
25288
25289
25290
25291
25292
25293
25294
25295
25296
25297 && (!may_wrap || !char_can_wrap_before (it)))
25298 goto back_to_wrap;
25299
25300
25301
25302
25303 if (it->bidi_p)
25304 RECORD_MAX_MIN_POS (it);
25305 set_iterator_to_next (it, true);
25306 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25307 {
25308 if (!get_next_display_element (it))
25309 {
25310 row->exact_window_width_line_p = true;
25311 it->continuation_lines_width = 0;
25312 it->font_height = Qnil;
25313 it->voffset = 0;
25314 row->continued_p = false;
25315 row->ends_at_zv_p = true;
25316 }
25317 else if (ITERATOR_AT_END_OF_LINE_P (it))
25318 {
25319 row->continued_p = false;
25320 row->exact_window_width_line_p = true;
25321 }
25322
25323
25324 else if (wrap_row_used > 0
25325
25326
25327
25328
25329
25330
25331
25332
25333
25334 && (!may_wrap || !char_can_wrap_before (it)))
25335 goto back_to_wrap;
25336
25337 }
25338 }
25339 else if (it->bidi_p)
25340 RECORD_MAX_MIN_POS (it);
25341 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25342 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25343 extend_face_to_end_of_line (it);
25344 }
25345 else if (CHAR_GLYPH_PADDING_P (*glyph)
25346 && !FRAME_WINDOW_P (it->f))
25347 {
25348
25349
25350
25351 if (row->reversed_p)
25352 unproduce_glyphs (it, row->used[TEXT_AREA]
25353 - n_glyphs_before);
25354 row->used[TEXT_AREA] = n_glyphs_before;
25355
25356
25357
25358 while (row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]
25359 < row->glyphs[1 + TEXT_AREA])
25360 produce_special_glyphs (it, IT_CONTINUATION);
25361
25362 row->continued_p = true;
25363 it->current_x = x_before;
25364 it->continuation_lines_width += x_before;
25365
25366
25367
25368 it->max_ascent = ascent;
25369 it->max_descent = descent;
25370 it->max_phys_ascent = phys_ascent;
25371 it->max_phys_descent = phys_descent;
25372 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25373 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25374 extend_face_to_end_of_line (it);
25375 }
25376 else if (wrap_row_used > 0)
25377 {
25378 back_to_wrap:
25379 if (row->reversed_p)
25380 unproduce_glyphs (it,
25381 row->used[TEXT_AREA] - wrap_row_used);
25382 RESTORE_IT (it, &wrap_it, wrap_data);
25383 it->continuation_lines_width += wrap_x;
25384 row->used[TEXT_AREA] = wrap_row_used;
25385 row->ascent = wrap_row_ascent;
25386 row->height = wrap_row_height;
25387 row->phys_ascent = wrap_row_phys_ascent;
25388 row->phys_height = wrap_row_phys_height;
25389 row->extra_line_spacing = wrap_row_extra_line_spacing;
25390 min_pos = wrap_row_min_pos;
25391 min_bpos = wrap_row_min_bpos;
25392 max_pos = wrap_row_max_pos;
25393 max_bpos = wrap_row_max_bpos;
25394 row->continued_p = true;
25395 row->ends_at_zv_p = false;
25396 row->exact_window_width_line_p = false;
25397
25398
25399
25400 extend_face_to_end_of_line (it);
25401 }
25402 else if ((it->what == IT_CHARACTER
25403 || it->what == IT_STRETCH
25404 || it->what == IT_COMPOSITION)
25405 && it->c == '\t' && FRAME_WINDOW_P (it->f))
25406 {
25407
25408
25409
25410
25411
25412 if ((row->reversed_p
25413 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25414 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25415 produce_special_glyphs (it, IT_CONTINUATION);
25416 it->continuation_lines_width += it->last_visible_x;
25417 row->ends_in_middle_of_char_p = true;
25418 row->continued_p = true;
25419 glyph->pixel_width = it->last_visible_x - x;
25420 it->starts_in_middle_of_char_p = true;
25421 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25422 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25423 extend_face_to_end_of_line (it);
25424 }
25425 else
25426 {
25427
25428
25429
25430 if (row->reversed_p)
25431 unproduce_glyphs (it, row->used[TEXT_AREA]
25432 - (n_glyphs_before + i));
25433 row->used[TEXT_AREA] = n_glyphs_before + i;
25434
25435
25436 it->current_x = x_before;
25437 it->continuation_lines_width += x;
25438 if (!FRAME_WINDOW_P (it->f)
25439 || (row->reversed_p
25440 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25441 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25442 produce_special_glyphs (it, IT_CONTINUATION);
25443 row->continued_p = true;
25444
25445 extend_face_to_end_of_line (it);
25446
25447 if (nglyphs > 1 && i > 0)
25448 {
25449 row->ends_in_middle_of_char_p = true;
25450 it->starts_in_middle_of_char_p = true;
25451 }
25452
25453
25454
25455 it->max_ascent = ascent;
25456 it->max_descent = descent;
25457 it->max_phys_ascent = phys_ascent;
25458 it->max_phys_descent = phys_descent;
25459 }
25460
25461 break;
25462 }
25463 else if (new_x > it->first_visible_x)
25464 {
25465
25466 ++it->hpos;
25467
25468
25469
25470
25471 if (it->bidi_p)
25472 RECORD_MAX_MIN_POS (it);
25473
25474 if (x < it->first_visible_x && !row->reversed_p
25475 && !line_number_needed)
25476
25477
25478
25479
25480
25481
25482 row->x = x - it->first_visible_x;
25483
25484
25485
25486
25487
25488
25489 if (row->reversed_p
25490 && new_x > it->last_visible_x
25491 && !line_number_needed
25492 && !(it->line_wrap == TRUNCATE
25493 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0))
25494 {
25495 eassert (FRAME_WINDOW_P (it->f));
25496 row->x = it->last_visible_x - new_x;
25497 }
25498 }
25499 else
25500 {
25501
25502
25503
25504
25505
25506 eassert (it->first_visible_x <= it->last_visible_x);
25507 }
25508 }
25509
25510
25511 if (it->bidi_p && nglyphs == 0)
25512 RECORD_MAX_MIN_POS (it);
25513
25514 row->ascent = max (row->ascent, it->max_ascent);
25515 row->height = max (row->height, it->max_ascent + it->max_descent);
25516 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25517 row->phys_height = max (row->phys_height,
25518 it->max_phys_ascent + it->max_phys_descent);
25519 row->extra_line_spacing = max (row->extra_line_spacing,
25520 it->max_extra_line_spacing);
25521
25522
25523 if (row->continued_p || row->ends_at_zv_p)
25524 break;
25525 }
25526
25527 at_end_of_line:
25528
25529
25530
25531 if (ITERATOR_AT_END_OF_LINE_P (it))
25532 {
25533 int used_before = row->used[TEXT_AREA];
25534
25535 row->ends_in_newline_from_string_p = STRINGP (it->object);
25536
25537
25538
25539 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25540 append_space_for_newline (it, false);
25541
25542
25543 extend_face_to_end_of_line (it);
25544
25545
25546 if (used_before == 0)
25547 row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
25548
25549
25550
25551 it->eol_pos = it->current.pos;
25552
25553
25554 set_iterator_to_next (it, true);
25555 it->continuation_lines_width = 0;
25556 break;
25557 }
25558
25559
25560
25561
25562
25563
25564
25565
25566 bool overwide_wrap_prefix =
25567 CONSP (it->object) && EQ (XCAR (it->object), Qspace)
25568 && it->sp > 0 && it->method == GET_FROM_STRETCH
25569 && it->current_x >= it->last_visible_x
25570 && it->continuation_lines_width > 0
25571 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
25572
25573
25574
25575 if (!overwide_wrap_prefix)
25576 set_iterator_to_next (it, true);
25577
25578
25579
25580 if (it->line_wrap == TRUNCATE
25581 && ((FRAME_WINDOW_P (it->f)
25582
25583
25584
25585
25586 && ((row->reversed_p
25587 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25588 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))
25589 || it->what == IT_IMAGE))
25590 ? (it->current_x >= it->last_visible_x)
25591 : (it->current_x > it->last_visible_x)))
25592 {
25593
25594 if (!FRAME_WINDOW_P (it->f)
25595 || (row->reversed_p
25596 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25597 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25598 {
25599 int i, n;
25600
25601 if (!row->reversed_p)
25602 {
25603 for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
25604 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
25605 break;
25606 }
25607 else
25608 {
25609 for (i = 0; i < row->used[TEXT_AREA]; i++)
25610 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
25611 break;
25612
25613
25614
25615
25616
25617 unproduce_glyphs (it, i + 1);
25618
25619 i = row->used[TEXT_AREA] - (i + 1);
25620 }
25621
25622
25623
25624
25625 if (it->current_x > it->last_visible_x)
25626 {
25627 it->current_x = x_before;
25628 if (!FRAME_WINDOW_P (it->f))
25629 {
25630 for (n = row->used[TEXT_AREA]; i < n; ++i)
25631 {
25632 row->used[TEXT_AREA] = i;
25633 produce_special_glyphs (it, IT_TRUNCATION);
25634 }
25635 }
25636 else
25637 {
25638 row->used[TEXT_AREA] = i;
25639 produce_special_glyphs (it, IT_TRUNCATION);
25640 }
25641 it->hpos = hpos_before;
25642 }
25643 }
25644 else if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25645 {
25646
25647 if (!get_next_display_element (it))
25648 {
25649 it->continuation_lines_width = 0;
25650 it->font_height = Qnil;
25651 it->voffset = 0;
25652 row->ends_at_zv_p = true;
25653 row->exact_window_width_line_p = true;
25654 break;
25655 }
25656 if (ITERATOR_AT_END_OF_LINE_P (it))
25657 {
25658 row->exact_window_width_line_p = true;
25659 goto at_end_of_line;
25660 }
25661 it->current_x = x_before;
25662 it->hpos = hpos_before;
25663 }
25664
25665 row->truncated_on_right_p = true;
25666 it->continuation_lines_width = 0;
25667 reseat_at_next_visible_line_start (it, false);
25668
25669
25670
25671
25672 if (IT_BYTEPOS (*it) > BEG_BYTE)
25673 row->ends_at_zv_p =
25674 IT_BYTEPOS (*it) >= ZV_BYTE
25675 && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n');
25676 else
25677 row->ends_at_zv_p = false;
25678 break;
25679 }
25680 }
25681
25682 if (wrap_data)
25683 bidi_unshelve_cache (wrap_data, true);
25684
25685
25686
25687 if (it->first_visible_x
25688 && IT_CHARPOS (*it) != CHARPOS (row->start.pos))
25689 {
25690 if (!FRAME_WINDOW_P (it->f)
25691 || (((row->reversed_p
25692 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
25693 : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
25694
25695
25696 && row->glyphs[TEXT_AREA]->type != IMAGE_GLYPH))
25697 insert_left_trunc_glyphs (it);
25698 row->truncated_on_left_p = true;
25699 }
25700
25701
25702
25703
25704
25705
25706 row->end = it->current;
25707 if (!it->bidi_p)
25708 {
25709 row->minpos = row->start.pos;
25710 row->maxpos = row->end.pos;
25711 }
25712 else
25713 {
25714
25715
25716
25717
25718 find_row_edges (it, row, min_pos, min_bpos, max_pos, max_bpos);
25719 }
25720
25721
25722
25723
25724
25725 if ((MATRIX_ROW_DISPLAYS_TEXT_P (row) || !overlay_arrow_seen)
25726 && (overlay_arrow_string = overlay_arrow_at_row (it, row),
25727 !NILP (overlay_arrow_string)))
25728 {
25729
25730 if (STRINGP (overlay_arrow_string))
25731 {
25732 struct glyph_row *arrow_row
25733 = get_overlay_arrow_glyph_row (it->w, overlay_arrow_string);
25734 struct glyph *glyph = arrow_row->glyphs[TEXT_AREA];
25735 struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA];
25736 struct glyph *p = row->glyphs[TEXT_AREA];
25737 struct glyph *p2, *end;
25738
25739
25740 while (glyph < arrow_end)
25741 *p++ = *glyph++;
25742
25743
25744 p2 = p;
25745 end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
25746 while (p2 < end && CHAR_GLYPH_PADDING_P (*p2))
25747 ++p2;
25748 if (p2 > p)
25749 {
25750 while (p2 < end)
25751 *p++ = *p2++;
25752 row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
25753 }
25754 }
25755 else
25756 {
25757 eassert (FIXNUMP (overlay_arrow_string));
25758 row->overlay_arrow_bitmap = XFIXNUM (overlay_arrow_string);
25759 }
25760 overlay_arrow_seen = true;
25761 }
25762
25763
25764 if (!NILP (Vshow_trailing_whitespace))
25765 highlight_trailing_whitespace (it);
25766
25767
25768 compute_line_metrics (it);
25769
25770
25771
25772
25773
25774
25775
25776 row->ends_in_ellipsis_p
25777 = (it->method == GET_FROM_DISPLAY_VECTOR
25778 && it->ellipsis_p);
25779
25780
25781 row->left_user_fringe_bitmap = it->left_user_fringe_bitmap;
25782 row->left_user_fringe_face_id = it->left_user_fringe_face_id;
25783 row->right_user_fringe_bitmap = it->right_user_fringe_bitmap;
25784 row->right_user_fringe_face_id = it->right_user_fringe_face_id;
25785
25786 it->left_user_fringe_bitmap = 0;
25787 it->left_user_fringe_face_id = 0;
25788 it->right_user_fringe_bitmap = 0;
25789 it->right_user_fringe_face_id = 0;
25790
25791
25792
25793
25794
25795
25796 if (MINI_WINDOW_P (it->w) && it->line_wrap == TRUNCATE
25797 && FRAME_WINDOW_P (it->f) && !cursor_in_echo_area)
25798 row->redraw_fringe_bitmaps_p = true;
25799
25800
25801 cvpos = it->w->cursor.vpos;
25802 if ((cvpos < 0
25803
25804
25805
25806
25807
25808
25809
25810
25811 || (it->bidi_p
25812 && !MATRIX_ROW (it->w->desired_matrix, cvpos)->ends_at_zv_p))
25813 && PT >= MATRIX_ROW_START_CHARPOS (row)
25814 && PT <= MATRIX_ROW_END_CHARPOS (row)
25815 && cursor_row_p (row))
25816 set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
25817
25818
25819
25820
25821
25822 it->current_x = it->hpos = 0;
25823 it->current_y += row->height;
25824
25825
25826 if (hscroll_this_line)
25827 {
25828 it->first_visible_x = first_visible_x;
25829 it->last_visible_x = last_visible_x;
25830 }
25831 SET_TEXT_POS (it->eol_pos, 0, 0);
25832 ++it->vpos;
25833 ++it->glyph_row;
25834
25835
25836
25837
25838 if (it->glyph_row < MATRIX_BOTTOM_TEXT_ROW (it->w->desired_matrix, it->w))
25839 it->glyph_row->reversed_p = row->reversed_p;
25840 it->start = row->end;
25841 return MATRIX_ROW_DISPLAYS_TEXT_P (row);
25842
25843 #undef RECORD_MAX_MIN_POS
25844 }
25845
25846 DEFUN ("current-bidi-paragraph-direction", Fcurrent_bidi_paragraph_direction,
25847 Scurrent_bidi_paragraph_direction, 0, 1, 0,
25848 doc:
25849
25850
25851
25852
25853
25854
25855
25856
25857 )
25858 (Lisp_Object buffer)
25859 {
25860 struct buffer *buf = current_buffer;
25861 struct buffer *old = buf;
25862
25863 if (! NILP (buffer))
25864 {
25865 CHECK_BUFFER (buffer);
25866 buf = XBUFFER (buffer);
25867 }
25868
25869 if (NILP (BVAR (buf, bidi_display_reordering))
25870 || NILP (BVAR (buf, enable_multibyte_characters))
25871
25872
25873 || redisplay__inhibit_bidi)
25874 return Qleft_to_right;
25875 else if (!NILP (BVAR (buf, bidi_paragraph_direction)))
25876 return BVAR (buf, bidi_paragraph_direction);
25877 else
25878 {
25879
25880
25881
25882 struct bidi_it itb;
25883 ptrdiff_t pos = BUF_PT (buf);
25884 ptrdiff_t bytepos = BUF_PT_BYTE (buf);
25885 int c;
25886 void *itb_data = bidi_shelve_cache ();
25887
25888 set_buffer_temp (buf);
25889
25890
25891
25892
25893
25894 if (pos >= ZV && pos > BEGV)
25895 dec_both (&pos, &bytepos);
25896 AUTO_STRING (trailing_white_space, "[\f\t ]*\n");
25897 if (fast_looking_at (trailing_white_space,
25898 pos, bytepos, ZV, ZV_BYTE, Qnil) > 0)
25899 {
25900 while ((c = FETCH_BYTE (bytepos)) == '\n'
25901 || c == ' ' || c == '\t' || c == '\f')
25902 {
25903 if (bytepos <= BEGV_BYTE)
25904 break;
25905 bytepos--;
25906 pos--;
25907 }
25908 while (!CHAR_HEAD_P (FETCH_BYTE (bytepos)))
25909 bytepos--;
25910 }
25911 bidi_init_it (pos, bytepos, FRAME_WINDOW_P (SELECTED_FRAME ()), &itb);
25912 itb.paragraph_dir = NEUTRAL_DIR;
25913 itb.string.s = NULL;
25914 itb.string.lstring = Qnil;
25915 itb.string.bufpos = 0;
25916 itb.string.from_disp_str = false;
25917 itb.string.unibyte = false;
25918
25919
25920
25921 itb.w = NULL;
25922 bidi_paragraph_init (NEUTRAL_DIR, &itb, true);
25923 bidi_unshelve_cache (itb_data, false);
25924 set_buffer_temp (old);
25925 switch (itb.paragraph_dir)
25926 {
25927 case L2R:
25928 return Qleft_to_right;
25929 break;
25930 case R2L:
25931 return Qright_to_left;
25932 break;
25933 default:
25934 emacs_abort ();
25935 }
25936 }
25937 }
25938
25939 DEFUN ("bidi-find-overridden-directionality",
25940 Fbidi_find_overridden_directionality,
25941 Sbidi_find_overridden_directionality, 3, 4, 0,
25942 doc:
25943
25944
25945
25946
25947
25948
25949
25950
25951
25952
25953
25954
25955
25956
25957
25958
25959
25960
25961
25962
25963
25964
25965
25966
25967
25968
25969
25970
25971
25972
25973
25974
25975
25976
25977
25978
25979 )
25980 (Lisp_Object from, Lisp_Object to, Lisp_Object object, Lisp_Object base_dir)
25981 {
25982 struct buffer *buf = current_buffer;
25983 struct buffer *old = buf;
25984 struct window *w = NULL;
25985 bool frame_window_p = FRAME_WINDOW_P (SELECTED_FRAME ());
25986 struct bidi_it itb;
25987 ptrdiff_t from_pos, to_pos, from_bpos;
25988 void *itb_data;
25989
25990 if (!NILP (object))
25991 {
25992 if (BUFFERP (object))
25993 buf = XBUFFER (object);
25994 else if (WINDOWP (object))
25995 {
25996 w = decode_live_window (object);
25997 buf = XBUFFER (w->contents);
25998 frame_window_p = FRAME_WINDOW_P (XFRAME (w->frame));
25999 }
26000 else
26001 CHECK_STRING (object);
26002 }
26003
26004 if (STRINGP (object))
26005 {
26006
26007
26008 if (!STRING_MULTIBYTE (object)
26009
26010
26011
26012 || redisplay__inhibit_bidi)
26013 return Qnil;
26014
26015 validate_subarray (object, from, to, SCHARS (object), &from_pos, &to_pos);
26016 if (from_pos >= SCHARS (object))
26017 return Qnil;
26018
26019
26020 itb_data = bidi_shelve_cache ();
26021 itb.paragraph_dir = NEUTRAL_DIR;
26022 itb.string.lstring = object;
26023 itb.string.s = NULL;
26024 itb.string.schars = SCHARS (object);
26025 itb.string.bufpos = 0;
26026 itb.string.from_disp_str = false;
26027 itb.string.unibyte = false;
26028 itb.w = w;
26029 bidi_init_it (0, 0, frame_window_p, &itb);
26030 }
26031 else
26032 {
26033
26034
26035 if (NILP (BVAR (buf, bidi_display_reordering))
26036 || NILP (BVAR (buf, enable_multibyte_characters))
26037
26038
26039
26040 || redisplay__inhibit_bidi)
26041 return Qnil;
26042
26043 set_buffer_temp (buf);
26044 validate_region (&from, &to);
26045 from_pos = XFIXNUM (from);
26046 to_pos = XFIXNUM (to);
26047 if (from_pos >= ZV)
26048 return Qnil;
26049
26050
26051 itb_data = bidi_shelve_cache ();
26052 from_bpos = CHAR_TO_BYTE (from_pos);
26053 if (from_pos == BEGV)
26054 {
26055 itb.charpos = BEGV;
26056 itb.bytepos = BEGV_BYTE;
26057 }
26058 else if (FETCH_BYTE (from_bpos - 1) == '\n')
26059 {
26060 itb.charpos = from_pos;
26061 itb.bytepos = from_bpos;
26062 }
26063 else
26064 itb.charpos = find_newline_no_quit (from_pos, CHAR_TO_BYTE (from_pos),
26065 -1, &itb.bytepos);
26066 itb.paragraph_dir = NEUTRAL_DIR;
26067 itb.string.s = NULL;
26068 itb.string.lstring = Qnil;
26069 itb.string.bufpos = 0;
26070 itb.string.from_disp_str = false;
26071 itb.string.unibyte = false;
26072 itb.w = w;
26073 bidi_init_it (itb.charpos, itb.bytepos, frame_window_p, &itb);
26074 }
26075
26076 ptrdiff_t found;
26077 bidi_dir_t bdir = EQ (base_dir, Qright_to_left) ? R2L : L2R;
26078 do {
26079 bidi_paragraph_init (bdir, &itb, false);
26080 while ((found = bidi_find_first_overridden (&itb)) < from_pos)
26081 ;
26082 } while (found == ZV && itb.ch == '\n' && itb.charpos < to_pos);
26083
26084 bidi_unshelve_cache (itb_data, false);
26085 set_buffer_temp (old);
26086
26087 return (from_pos <= found && found < to_pos) ? make_fixnum (found) : Qnil;
26088 }
26089
26090 DEFUN ("move-point-visually", Fmove_point_visually,
26091 Smove_point_visually, 1, 1, 0,
26092 doc:
26093
26094
26095
26096 )
26097 (Lisp_Object direction)
26098 {
26099 struct window *w = XWINDOW (selected_window);
26100 struct buffer *b = XBUFFER (w->contents);
26101 struct glyph_row *row;
26102 int dir;
26103 Lisp_Object paragraph_dir;
26104
26105 #define ROW_GLYPH_NEWLINE_P(ROW,GLYPH) \
26106 (!(ROW)->continued_p \
26107 && NILP ((GLYPH)->object) \
26108 && (GLYPH)->type == CHAR_GLYPH \
26109 && (GLYPH)->u.ch == ' ' \
26110 && (GLYPH)->charpos >= 0 \
26111 && !(GLYPH)->avoid_cursor_p)
26112
26113 CHECK_FIXNUM (direction);
26114 dir = XFIXNUM (direction);
26115 if (dir > 0)
26116 dir = 1;
26117 else
26118 dir = -1;
26119
26120
26121
26122
26123 if (w->window_end_valid
26124 && !windows_or_buffers_changed
26125 && b
26126 && !b->clip_changed
26127 && !b->prevent_redisplay_optimizations_p
26128 && !window_outdated (w)
26129
26130
26131
26132 && w->last_point == BUF_PT (b)
26133 && w->cursor.vpos >= 0
26134 && w->cursor.vpos < w->current_matrix->nrows
26135 && (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos))->enabled_p)
26136 {
26137 struct glyph *g = row->glyphs[TEXT_AREA];
26138 struct glyph *e = dir > 0 ? g + row->used[TEXT_AREA] : g - 1;
26139 struct glyph *gpt = g + w->cursor.hpos;
26140
26141 for (g = gpt + dir; (dir > 0 ? g < e : g > e); g += dir)
26142 {
26143 if (BUFFERP (g->object) && g->charpos != PT)
26144 {
26145 SET_PT (g->charpos);
26146 w->cursor.vpos = -1;
26147 return make_fixnum (PT);
26148 }
26149 else if (!NILP (g->object) && !EQ (g->object, gpt->object))
26150 {
26151 ptrdiff_t new_pos;
26152
26153 if (BUFFERP (gpt->object))
26154 {
26155 new_pos = PT;
26156 if ((gpt->resolved_level - row->reversed_p) % 2 == 0)
26157 new_pos += (row->reversed_p ? -dir : dir);
26158 else
26159 new_pos -= (row->reversed_p ? -dir : dir);
26160 new_pos = clip_to_bounds (BEGV, new_pos, ZV);
26161
26162
26163 if (new_pos == PT)
26164 break;
26165 }
26166 else if (BUFFERP (g->object))
26167 new_pos = g->charpos;
26168 else
26169 break;
26170 SET_PT (new_pos);
26171 w->cursor.vpos = -1;
26172 return make_fixnum (PT);
26173 }
26174 else if (ROW_GLYPH_NEWLINE_P (row, g))
26175 {
26176
26177
26178
26179 if (g->charpos > 0)
26180 SET_PT (g->charpos);
26181 else if (row->ends_at_zv_p && PT != ZV)
26182 SET_PT (ZV);
26183 else if (PT != MATRIX_ROW_END_CHARPOS (row) - 1)
26184 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26185 else
26186 break;
26187 w->cursor.vpos = -1;
26188 return make_fixnum (PT);
26189 }
26190 }
26191 if (g == e || NILP (g->object))
26192 {
26193 if (row->truncated_on_left_p || row->truncated_on_right_p)
26194 goto simulate_display;
26195 if (!row->reversed_p)
26196 row += dir;
26197 else
26198 row -= dir;
26199 if (!(MATRIX_FIRST_TEXT_ROW (w->current_matrix) <= row
26200 && row < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)))
26201 goto simulate_display;
26202
26203 if (dir > 0)
26204 {
26205 if (row->reversed_p && !row->continued_p)
26206 {
26207 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26208 w->cursor.vpos = -1;
26209 return make_fixnum (PT);
26210 }
26211 g = row->glyphs[TEXT_AREA];
26212 e = g + row->used[TEXT_AREA];
26213 for ( ; g < e; g++)
26214 {
26215 if (BUFFERP (g->object)
26216
26217
26218
26219 || ROW_GLYPH_NEWLINE_P (row, g)
26220
26221
26222 || (row->ends_at_zv_p
26223 && !row->reversed_p
26224 && NILP (g->object)
26225 && g->type == CHAR_GLYPH
26226 && g->u.ch == ' '))
26227 {
26228 if (g->charpos > 0)
26229 SET_PT (g->charpos);
26230 else if (!row->reversed_p
26231 && row->ends_at_zv_p
26232 && PT != ZV)
26233 SET_PT (ZV);
26234 else
26235 continue;
26236 w->cursor.vpos = -1;
26237 return make_fixnum (PT);
26238 }
26239 }
26240 }
26241 else
26242 {
26243 if (!row->reversed_p && !row->continued_p)
26244 {
26245 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26246 w->cursor.vpos = -1;
26247 return make_fixnum (PT);
26248 }
26249 e = row->glyphs[TEXT_AREA];
26250 g = e + row->used[TEXT_AREA] - 1;
26251 for ( ; g >= e; g--)
26252 {
26253 if (BUFFERP (g->object)
26254 || (ROW_GLYPH_NEWLINE_P (row, g)
26255 && g->charpos > 0)
26256
26257
26258
26259 || g->type == STRETCH_GLYPH
26260 || (row->ends_at_zv_p
26261 && row->reversed_p
26262 && NILP (g->object)
26263 && g->type == CHAR_GLYPH
26264 && g->u.ch == ' '))
26265 {
26266 if (g->charpos > 0)
26267 SET_PT (g->charpos);
26268 else if (row->reversed_p
26269 && row->ends_at_zv_p
26270 && PT != ZV)
26271 SET_PT (ZV);
26272 else
26273 continue;
26274 w->cursor.vpos = -1;
26275 return make_fixnum (PT);
26276 }
26277 }
26278 }
26279 }
26280 }
26281
26282 simulate_display:
26283
26284
26285
26286
26287 if (b)
26288 paragraph_dir = Fcurrent_bidi_paragraph_direction (w->contents);
26289 else
26290 paragraph_dir = Qleft_to_right;
26291 if (EQ (paragraph_dir, Qright_to_left))
26292 dir = -dir;
26293 if (PT <= BEGV && dir < 0)
26294 xsignal0 (Qbeginning_of_buffer);
26295 else if (PT >= ZV && dir > 0)
26296 xsignal0 (Qend_of_buffer);
26297 else
26298 {
26299 struct text_pos pt;
26300 struct it it;
26301 int pt_x, target_x, pixel_width, pt_vpos;
26302 bool at_eol_p;
26303 bool overshoot_expected = false;
26304 bool target_is_eol_p = false;
26305 void *itdata = bidi_shelve_cache ();
26306
26307
26308 SET_TEXT_POS (pt, PT, PT_BYTE);
26309 start_display (&it, w, pt);
26310
26311
26312
26313
26314
26315
26316 if (it.line_wrap == TRUNCATE)
26317 it.last_visible_x = DISP_INFINITY;
26318
26319 if (it.cmp_it.id < 0
26320 && it.method == GET_FROM_STRING
26321 && it.area == TEXT_AREA
26322 && it.string_from_display_prop_p
26323 && (it.sp > 0 && it.stack[it.sp - 1].method == GET_FROM_BUFFER))
26324 overshoot_expected = true;
26325
26326
26327
26328
26329
26330 reseat:
26331 reseat_at_previous_visible_line_start (&it);
26332 it.current_x = it.hpos = it.current_y = it.vpos = 0;
26333 if (IT_CHARPOS (it) != PT)
26334 {
26335 move_it_to (&it, overshoot_expected ? PT - 1 : PT,
26336 -1, -1, -1, MOVE_TO_POS);
26337
26338
26339
26340 if (it.method == GET_FROM_DISPLAY_VECTOR
26341 && it.current.dpvec_index > 0
26342 && !overshoot_expected)
26343 {
26344 overshoot_expected = true;
26345 goto reseat;
26346 }
26347 else if (IT_CHARPOS (it) != PT && !overshoot_expected)
26348 move_it_in_display_line (&it, PT, -1, MOVE_TO_POS);
26349 }
26350 pt_x = it.current_x;
26351 pt_vpos = it.vpos;
26352 if (dir > 0 || overshoot_expected)
26353 {
26354 struct glyph_row *row = it.glyph_row;
26355
26356
26357
26358
26359 if (pt_x == 0)
26360 get_next_display_element (&it);
26361 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
26362 it.glyph_row = NULL;
26363 PRODUCE_GLYPHS (&it);
26364 it.glyph_row = row;
26365
26366
26367
26368 it.current_x = pt_x;
26369 }
26370 else
26371 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
26372 pixel_width = it.pixel_width;
26373 if (overshoot_expected && at_eol_p)
26374 pixel_width = 0;
26375 else if (pixel_width <= 0)
26376 pixel_width = 1;
26377
26378
26379
26380
26381 if (overshoot_expected)
26382 {
26383 if (it.bidi_p)
26384 pt_x += pixel_width * it.bidi_it.scan_dir;
26385 else
26386 pt_x += pixel_width;
26387 }
26388
26389
26390
26391
26392
26393
26394
26395 if (dir > 0)
26396 target_x = pt_x + pixel_width;
26397 else
26398 target_x = pt_x - (!FRAME_WINDOW_P (it.f)) * pixel_width;
26399
26400
26401
26402
26403
26404 if (dir < 0)
26405 {
26406 if (pt_x > 0)
26407 {
26408 start_display (&it, w, pt);
26409 if (it.line_wrap == TRUNCATE)
26410 it.last_visible_x = DISP_INFINITY;
26411 reseat_at_previous_visible_line_start (&it);
26412 it.current_x = it.current_y = it.hpos = 0;
26413 if (pt_vpos != 0)
26414 move_it_by_lines (&it, pt_vpos);
26415 }
26416 else
26417 {
26418 move_it_by_lines (&it, -1);
26419 target_x = it.last_visible_x - !FRAME_WINDOW_P (it.f);
26420 target_is_eol_p = true;
26421
26422
26423
26424
26425
26426
26427
26428
26429
26430
26431 if (!FRAME_WINDOW_P (it.f) && it.line_wrap == WORD_WRAP)
26432 {
26433 void *it_data = NULL;
26434 struct it it2;
26435
26436 SAVE_IT (it2, it, it_data);
26437 move_it_in_display_line_to (&it, ZV, target_x,
26438 MOVE_TO_POS | MOVE_TO_X);
26439
26440
26441 if (it.current_x != target_x)
26442 target_x = it.current_x - 1;
26443 RESTORE_IT (&it, &it2, it_data);
26444 }
26445 }
26446 }
26447 else
26448 {
26449 if (at_eol_p
26450 || (target_x >= it.last_visible_x
26451 && it.line_wrap != TRUNCATE))
26452 {
26453 if (pt_x > 0)
26454 move_it_by_lines (&it, 0);
26455 move_it_by_lines (&it, 1);
26456 target_x = 0;
26457 }
26458 }
26459
26460
26461
26462
26463
26464
26465
26466 if (FRAME_WINDOW_P (it.f) && dir < 0)
26467 {
26468 struct text_pos new_pos;
26469 enum move_it_result rc = MOVE_X_REACHED;
26470
26471 if (it.current_x == 0)
26472 get_next_display_element (&it);
26473 if (it.what == IT_COMPOSITION)
26474 {
26475 new_pos.charpos = it.cmp_it.charpos;
26476 new_pos.bytepos = -1;
26477 }
26478 else
26479 new_pos = it.current.pos;
26480
26481 while (it.current_x + it.pixel_width <= target_x
26482 && (rc == MOVE_X_REACHED
26483
26484
26485
26486 || (it.line_wrap == WORD_WRAP
26487 && rc == MOVE_POS_MATCH_OR_ZV)))
26488 {
26489 int new_x = it.current_x + it.pixel_width;
26490
26491
26492
26493
26494
26495
26496
26497 if (it.what == IT_COMPOSITION)
26498 {
26499 new_pos.charpos = it.cmp_it.charpos;
26500 new_pos.bytepos = -1;
26501 }
26502 else
26503 new_pos = it.current.pos;
26504 if (new_x == it.current_x)
26505 new_x++;
26506 rc = move_it_in_display_line_to (&it, ZV, new_x,
26507 MOVE_TO_POS | MOVE_TO_X);
26508 if (ITERATOR_AT_END_OF_LINE_P (&it) && !target_is_eol_p)
26509 break;
26510 }
26511
26512
26513 if (new_pos.bytepos == -1)
26514 new_pos.bytepos = CHAR_TO_BYTE (new_pos.charpos);
26515 it.current.pos = new_pos;
26516 }
26517 else if (it.current_x != target_x)
26518 move_it_in_display_line_to (&it, ZV, target_x, MOVE_TO_POS | MOVE_TO_X);
26519
26520
26521
26522 if (dir > 0)
26523 {
26524 while (IT_CHARPOS (it) == PT)
26525 {
26526 set_iterator_to_next (&it, false);
26527 if (!get_next_display_element (&it))
26528 break;
26529 }
26530 }
26531
26532
26533 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
26534 bidi_unshelve_cache (itdata, false);
26535 }
26536
26537 return make_fixnum (PT);
26538
26539 #undef ROW_GLYPH_NEWLINE_P
26540 }
26541
26542 DEFUN ("bidi-resolved-levels", Fbidi_resolved_levels,
26543 Sbidi_resolved_levels, 0, 1, 0,
26544 doc:
26545
26546
26547
26548
26549
26550
26551
26552
26553
26554
26555
26556
26557
26558
26559
26560
26561
26562
26563
26564
26565
26566
26567
26568
26569
26570 )
26571 (Lisp_Object vpos)
26572 {
26573 struct window *w = XWINDOW (selected_window);
26574 struct buffer *b = XBUFFER (w->contents);
26575 int nrow;
26576 struct glyph_row *row;
26577
26578 if (NILP (vpos))
26579 {
26580 int d1, d2, d3, d4, d5;
26581
26582 pos_visible_p (w, PT, &d1, &d2, &d3, &d4, &d5, &nrow);
26583 }
26584 else
26585 {
26586 CHECK_FIXNUM (vpos);
26587 nrow = XFIXNUM (vpos);
26588 }
26589
26590
26591 if (w->window_end_valid
26592 && !windows_or_buffers_changed
26593 && b
26594 && !b->clip_changed
26595 && !b->prevent_redisplay_optimizations_p
26596 && !window_outdated (w)
26597 && nrow >= 0
26598 && nrow < w->current_matrix->nrows
26599 && (row = MATRIX_ROW (w->current_matrix, nrow))->enabled_p
26600 && MATRIX_ROW_DISPLAYS_TEXT_P (row))
26601 {
26602 struct glyph *g, *e, *g1;
26603 int nglyphs, i;
26604 Lisp_Object levels;
26605
26606 if (!row->reversed_p)
26607 {
26608 g = g1 = row->glyphs[TEXT_AREA];
26609 e = g + row->used[TEXT_AREA];
26610
26611
26612
26613 while (g < e
26614 && NILP (g->object)
26615 && g->charpos < 0)
26616 g++;
26617 g1 = g;
26618
26619
26620 for (nglyphs = 0; g < e && !NILP (g->object); g++)
26621 nglyphs++;
26622
26623
26624 levels = make_uninit_vector (nglyphs);
26625 for (i = 0; g1 < g; i++, g1++)
26626 ASET (levels, i, make_fixnum (g1->resolved_level));
26627 }
26628 else
26629 {
26630 g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
26631 e = row->glyphs[TEXT_AREA] - 1;
26632 while (g > e
26633 && NILP (g->object)
26634 && g->charpos < 0)
26635 g--;
26636 g1 = g;
26637 for (nglyphs = 0; g > e && !NILP (g->object); g--)
26638 nglyphs++;
26639 levels = make_uninit_vector (nglyphs);
26640 for (i = 0; g1 > g; i++, g1--)
26641 ASET (levels, i, make_fixnum (g1->resolved_level));
26642 }
26643 return levels;
26644 }
26645 else
26646 return Qnil;
26647 }
26648
26649
26650
26651
26652
26653
26654
26655
26656
26657
26658
26659
26660
26661
26662
26663
26664
26665 static void
26666 display_menu_bar (struct window *w)
26667 {
26668 struct frame *f = XFRAME (WINDOW_FRAME (w));
26669 struct it it;
26670 Lisp_Object items;
26671 int i;
26672
26673
26674 #ifdef HAVE_NTGUI
26675 if (FRAME_W32_P (f))
26676 return;
26677 #endif
26678 #if defined (HAVE_PGTK)
26679 if (FRAME_PGTK_P (f))
26680 return;
26681 #endif
26682
26683 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
26684 if (FRAME_X_P (f))
26685 return;
26686 #endif
26687
26688 #ifdef HAVE_NS
26689 if (FRAME_NS_P (f))
26690 return;
26691 #endif
26692
26693 #ifdef HAVE_HAIKU
26694 if (FRAME_HAIKU_P (f))
26695 return;
26696 #endif
26697
26698 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
26699 eassert (!FRAME_WINDOW_P (f));
26700 init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
26701 it.first_visible_x = 0;
26702 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
26703 #elif defined (HAVE_X_WINDOWS) || defined (HAVE_ANDROID)
26704 struct window *menu_window = NULL;
26705 struct face *face = FACE_FROM_ID (f, MENU_FACE_ID);
26706
26707 if (FRAME_WINDOW_P (f))
26708 {
26709
26710
26711 menu_window = XWINDOW (f->menu_bar_window);
26712 init_iterator (&it, menu_window, -1, -1,
26713 menu_window->desired_matrix->rows,
26714 MENU_FACE_ID);
26715 }
26716 else
26717 #endif
26718 {
26719
26720
26721 init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
26722 MENU_FACE_ID);
26723 it.first_visible_x = 0;
26724 it.last_visible_x = FRAME_COLS (f);
26725 }
26726
26727
26728
26729
26730 it.paragraph_embedding = L2R;
26731
26732
26733 for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
26734 {
26735 struct glyph_row *row = it.glyph_row + i;
26736 clear_glyph_row (row);
26737 row->enabled_p = true;
26738 row->full_width_p = true;
26739 row->reversed_p = false;
26740 }
26741
26742
26743 items = FRAME_MENU_BAR_ITEMS (it.f);
26744 for (i = 0; i < ASIZE (items); i += 4)
26745 {
26746 Lisp_Object string;
26747
26748
26749 string = AREF (items, i + 1);
26750 if (NILP (string))
26751 break;
26752
26753
26754 ASET (items, i + 3, make_fixnum (it.hpos));
26755
26756
26757 if (it.current_x < it.last_visible_x)
26758 display_string (NULL, string, Qnil, 0, 0, &it,
26759 SCHARS (string) + 1, 0, 0, STRING_MULTIBYTE (string));
26760 }
26761
26762
26763 if (it.current_x < it.last_visible_x)
26764 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
26765
26766
26767 compute_line_metrics (&it);
26768 it.glyph_row->full_width_p = true;
26769 it.glyph_row->continued_p = false;
26770 it.glyph_row->truncated_on_left_p = false;
26771 it.glyph_row->truncated_on_right_p = false;
26772
26773
26774
26775
26776
26777 #if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
26778
26779 extend_face_to_end_of_line (&it);
26780 if (face->box != FACE_NO_BOX)
26781 {
26782 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
26783 + it.glyph_row->used[TEXT_AREA] - 1);
26784 int box_thickness = face->box_vertical_line_width;
26785 last->right_box_line_p = true;
26786
26787
26788
26789
26790
26791
26792 if (box_thickness > 0)
26793 last->pixel_width += max (0, (box_thickness
26794 - (it.current_x - it.last_visible_x)));
26795 }
26796
26797
26798
26799 if (FRAME_WINDOW_P (it.f) && menu_window)
26800 {
26801 struct glyph_row *row;
26802 int delta_height;
26803
26804 row = it.glyph_row;
26805 delta_height
26806 = ((row->y + row->height)
26807 - WINDOW_BOX_HEIGHT_NO_MODE_LINE (menu_window));
26808
26809 if (delta_height != 0)
26810 {
26811 FRAME_MENU_BAR_HEIGHT (it.f) += delta_height;
26812 adjust_frame_size (it.f, -1, -1, 3, false, Qmenu_bar_lines);
26813 }
26814 }
26815 #endif
26816 }
26817
26818
26819
26820
26821 #ifndef HAVE_ANDROID
26822
26823
26824 static void
26825 deep_copy_glyph_row (struct glyph_row *to, struct glyph_row *from)
26826 {
26827 struct glyph *pointers[1 + LAST_AREA];
26828 int to_used = to->used[TEXT_AREA];
26829
26830
26831 memcpy (pointers, to->glyphs, sizeof to->glyphs);
26832
26833
26834 *to = *from;
26835
26836
26837 memcpy (to->glyphs, pointers, sizeof to->glyphs);
26838
26839
26840 memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA],
26841 min (from->used[TEXT_AREA], to_used) * sizeof (struct glyph));
26842
26843
26844
26845 if (to_used > from->used[TEXT_AREA])
26846 fill_up_frame_row_with_spaces (to, to_used);
26847 }
26848
26849
26850
26851
26852
26853
26854
26855
26856
26857
26858
26859
26860
26861
26862
26863
26864
26865
26866
26867
26868
26869
26870 void
26871 display_tty_menu_item (const char *item_text, int width, int face_id,
26872 int x, int y, bool submenu)
26873 {
26874 struct it it;
26875 struct frame *f = SELECTED_FRAME ();
26876 struct window *w = XWINDOW (f->selected_window);
26877 struct glyph_row *row;
26878 size_t item_len = strlen (item_text);
26879
26880 eassert (FRAME_TERMCAP_P (f));
26881
26882
26883
26884
26885
26886
26887 if (y >= f->desired_matrix->nrows)
26888 return;
26889
26890 init_iterator (&it, w, -1, -1, f->desired_matrix->rows + y, MENU_FACE_ID);
26891 it.first_visible_x = 0;
26892 it.last_visible_x = FRAME_COLS (f) - 1;
26893 row = it.glyph_row;
26894
26895 deep_copy_glyph_row (row, f->current_matrix->rows + y);
26896 bool saved_width = row->full_width_p;
26897 row->full_width_p = true;
26898 bool saved_reversed = row->reversed_p;
26899 row->reversed_p = false;
26900 row->enabled_p = true;
26901
26902
26903
26904 eassert (x < f->desired_matrix->matrix_w);
26905 it.current_x = it.hpos = x;
26906 it.current_y = it.vpos = y;
26907 int saved_used = row->used[TEXT_AREA];
26908 bool saved_truncated = row->truncated_on_right_p;
26909 row->used[TEXT_AREA] = x;
26910 it.face_id = face_id;
26911 it.line_wrap = TRUNCATE;
26912
26913
26914
26915
26916
26917
26918 it.paragraph_embedding = L2R;
26919
26920
26921 display_string (" ", Qnil, Qnil, 0, 0, &it, 1, 0, FRAME_COLS (f) - 1, -1);
26922 width--;
26923
26924 if (submenu)
26925 {
26926 display_string (item_text, Qnil, Qnil, 0, 0, &it,
26927 item_len, 0, FRAME_COLS (f) - 1, -1);
26928 width -= item_len;
26929
26930 display_string (" >", Qnil, Qnil, 0, 0, &it, width, 0,
26931 FRAME_COLS (f) - 1, -1);
26932 }
26933 else
26934 display_string (item_text, Qnil, Qnil, 0, 0, &it,
26935 width, 0, FRAME_COLS (f) - 1, -1);
26936
26937 row->used[TEXT_AREA] = max (saved_used, row->used[TEXT_AREA]);
26938 row->truncated_on_right_p = saved_truncated;
26939 row->hash = row_hash (row);
26940 row->full_width_p = saved_width;
26941 row->reversed_p = saved_reversed;
26942 }
26943
26944 #endif
26945
26946
26947
26948
26949
26950
26951
26952
26953
26954
26955
26956 static int
26957 redisplay_mode_lines (Lisp_Object window, bool force)
26958 {
26959 int nwindows = 0;
26960
26961 while (!NILP (window))
26962 {
26963 struct window *w = XWINDOW (window);
26964
26965 if (WINDOWP (w->contents))
26966 nwindows += redisplay_mode_lines (w->contents, force);
26967 else if (force
26968 || FRAME_GARBAGED_P (XFRAME (w->frame))
26969 || !MATRIX_MODE_LINE_ROW (w->current_matrix)->enabled_p)
26970 {
26971 struct text_pos lpoint;
26972 struct buffer *old = current_buffer;
26973
26974
26975 SET_TEXT_POS (lpoint, PT, PT_BYTE);
26976 set_buffer_internal_1 (XBUFFER (w->contents));
26977
26978
26979
26980 if (!EQ (window, selected_window))
26981 {
26982 struct text_pos pt;
26983
26984 CLIP_TEXT_POS_FROM_MARKER (pt, w->pointm);
26985 TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
26986 }
26987
26988
26989 clear_glyph_matrix (w->desired_matrix);
26990 if (display_mode_lines (w))
26991 ++nwindows;
26992
26993
26994 set_buffer_internal_1 (old);
26995 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
26996 }
26997
26998 window = w->next;
26999 }
27000
27001 return nwindows;
27002 }
27003
27004
27005
27006
27007
27008
27009 static int
27010 display_mode_lines (struct window *w)
27011 {
27012 Lisp_Object old_selected_window = selected_window;
27013 Lisp_Object new_frame = w->frame;
27014 specpdl_ref count = SPECPDL_INDEX ();
27015 int n = 0;
27016
27017 record_unwind_protect (restore_selected_window, selected_window);
27018 record_unwind_protect
27019 (restore_frame_selected_window, XFRAME (new_frame)->selected_window);
27020
27021 if (window_wants_mode_line (w))
27022 {
27023 Lisp_Object window;
27024 Lisp_Object default_help
27025 = buffer_local_value (Qmode_line_default_help_echo, w->contents);
27026
27027
27028
27029 XSETWINDOW (window, w);
27030 if (FUNCTIONP (default_help))
27031 wset_mode_line_help_echo (w, safe_call1 (default_help, window));
27032 else if (STRINGP (default_help))
27033 wset_mode_line_help_echo (w, default_help);
27034 else
27035 wset_mode_line_help_echo (w, Qnil);
27036 }
27037
27038 selected_frame = new_frame;
27039
27040
27041 XSETWINDOW (selected_window, w);
27042 XFRAME (new_frame)->selected_window = selected_window;
27043
27044
27045 line_number_displayed = false;
27046 w->column_number_displayed = -1;
27047
27048 if (window_wants_mode_line (w))
27049 {
27050 Lisp_Object window_mode_line_format
27051 = window_parameter (w, Qmode_line_format);
27052 struct window *sel_w = XWINDOW (old_selected_window);
27053
27054
27055 display_mode_line (w,
27056 CURRENT_MODE_LINE_ACTIVE_FACE_ID_3 (sel_w, sel_w, w),
27057 NILP (window_mode_line_format)
27058 ? BVAR (current_buffer, mode_line_format)
27059 : window_mode_line_format);
27060 ++n;
27061 }
27062
27063 if (window_wants_tab_line (w))
27064 {
27065 Lisp_Object window_tab_line_format
27066 = window_parameter (w, Qtab_line_format);
27067
27068 display_mode_line (w, TAB_LINE_FACE_ID,
27069 NILP (window_tab_line_format)
27070 ? BVAR (current_buffer, tab_line_format)
27071 : window_tab_line_format);
27072 ++n;
27073 }
27074
27075 if (window_wants_header_line (w))
27076 {
27077 Lisp_Object window_header_line_format
27078 = window_parameter (w, Qheader_line_format);
27079
27080 display_mode_line (w, HEADER_LINE_FACE_ID,
27081 NILP (window_header_line_format)
27082 ? BVAR (current_buffer, header_line_format)
27083 : window_header_line_format);
27084 ++n;
27085 }
27086
27087 unbind_to (count, Qnil);
27088
27089 if (n > 0)
27090 w->must_be_updated_p = true;
27091 return n;
27092 }
27093
27094
27095
27096
27097
27098
27099
27100
27101 static int
27102 display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
27103 {
27104 struct it it;
27105 struct face *face;
27106 specpdl_ref count = SPECPDL_INDEX ();
27107
27108 init_iterator (&it, w, -1, -1, NULL, face_id);
27109
27110
27111 it.glyph_row->enabled_p = false;
27112 prepare_desired_row (w, it.glyph_row, true);
27113
27114 it.glyph_row->mode_line_p = true;
27115 if (face_id == TAB_LINE_FACE_ID)
27116 {
27117 it.glyph_row->tab_line_p = true;
27118 w->desired_matrix->tab_line_p = true;
27119 }
27120 else if (face_id == HEADER_LINE_FACE_ID)
27121 w->desired_matrix->header_line_p = true;
27122
27123
27124
27125
27126 it.paragraph_embedding = L2R;
27127
27128 record_unwind_protect (unwind_format_mode_line,
27129 format_mode_line_unwind_data (NULL, NULL,
27130 Qnil, false));
27131
27132
27133
27134
27135 push_kboard (FRAME_KBOARD (it.f));
27136 record_unwind_save_match_data ();
27137
27138 if (NILP (Vmode_line_compact)
27139 || face_id == HEADER_LINE_FACE_ID || face_id == TAB_LINE_FACE_ID)
27140 {
27141 mode_line_target = MODE_LINE_DISPLAY;
27142 display_mode_element (&it, 0, 0, 0, format, Qnil, false);
27143 }
27144 else
27145 {
27146 Lisp_Object mode_string = Fformat_mode_line (format, Qnil, Qnil, Qnil);
27147 if (EQ (Vmode_line_compact, Qlong)
27148 && WINDOW_TOTAL_COLS (w) >= SCHARS (mode_string))
27149 {
27150
27151
27152 display_string (NULL, mode_string, Qnil,
27153 0, 0, &it, 0, 0, 0,
27154 STRING_MULTIBYTE (mode_string));
27155 }
27156 else
27157 {
27158
27159 ptrdiff_t i = 0, i_byte = 0, start = 0;
27160 int prev = 0;
27161
27162 while (i < SCHARS (mode_string))
27163 {
27164 int c = fetch_string_char_advance (mode_string, &i, &i_byte);
27165 if (c == ' ' && prev == ' ')
27166 {
27167 display_string (NULL,
27168 Fsubstring (mode_string, make_fixnum (start),
27169 make_fixnum (i - 1)),
27170 Qnil, 0, 0, &it, 0, 0, 0,
27171 STRING_MULTIBYTE (mode_string));
27172
27173 while (c == ' ' && i < SCHARS (mode_string))
27174 c = fetch_string_char_advance (mode_string, &i, &i_byte);
27175 start = i - 1;
27176 }
27177 prev = c;
27178 }
27179
27180
27181 if (start < i)
27182 display_string (NULL,
27183 Fsubstring (mode_string, make_fixnum (start),
27184 make_fixnum (i)),
27185 Qnil, 0, 0, &it, 0, 0, 0,
27186 STRING_MULTIBYTE (mode_string));
27187 }
27188 }
27189 pop_kboard ();
27190
27191 unbind_to (count, Qnil);
27192
27193
27194 display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
27195
27196 compute_line_metrics (&it);
27197 it.glyph_row->full_width_p = true;
27198 it.glyph_row->continued_p = false;
27199 it.glyph_row->truncated_on_left_p = false;
27200 it.glyph_row->truncated_on_right_p = false;
27201
27202
27203 face = FACE_FROM_ID (it.f, face_id);
27204 extend_face_to_end_of_line (&it);
27205 if (face->box != FACE_NO_BOX)
27206 {
27207 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
27208 + it.glyph_row->used[TEXT_AREA] - 1);
27209 int box_thickness = face->box_vertical_line_width;
27210 last->right_box_line_p = true;
27211
27212
27213
27214
27215
27216
27217 if (box_thickness > 0)
27218 last->pixel_width += max (0, (box_thickness
27219 - (it.current_x - it.last_visible_x)));
27220 }
27221
27222 return it.glyph_row->height;
27223 }
27224
27225
27226
27227
27228 static Lisp_Object
27229 move_elt_to_front (Lisp_Object elt, Lisp_Object list)
27230 {
27231 register Lisp_Object tail, prev;
27232 register Lisp_Object tem;
27233
27234 tail = list;
27235 prev = Qnil;
27236 while (CONSP (tail))
27237 {
27238 tem = XCAR (tail);
27239
27240 if (EQ (elt, tem))
27241 {
27242
27243 if (NILP (prev))
27244 list = XCDR (tail);
27245 else
27246 Fsetcdr (prev, XCDR (tail));
27247
27248
27249 Fsetcdr (tail, list);
27250 return tail;
27251 }
27252 else
27253 prev = tail;
27254 tail = XCDR (tail);
27255 maybe_quit ();
27256 }
27257
27258
27259 return list;
27260 }
27261
27262
27263
27264
27265
27266 static Lisp_Object
27267 safe_set_text_properties (ptrdiff_t nargs, Lisp_Object *args)
27268 {
27269 eassert (nargs == 4);
27270 return Fset_text_properties (args[0], args[1], args[2], args[3]);
27271 }
27272
27273
27274
27275
27276
27277
27278
27279
27280
27281
27282
27283
27284
27285
27286
27287
27288
27289
27290
27291
27292
27293
27294
27295
27296
27297 static int
27298 display_mode_element (struct it *it, int depth, int field_width, int precision,
27299 Lisp_Object elt, Lisp_Object props, bool risky)
27300 {
27301 int n = 0, field, prec;
27302 bool literal = false;
27303
27304 tail_recurse:
27305 if (depth > 100)
27306 elt = build_string ("*too-deep*");
27307
27308 depth++;
27309
27310 switch (XTYPE (elt))
27311 {
27312 case Lisp_String:
27313 {
27314
27315 unsigned char c;
27316 ptrdiff_t offset = 0;
27317
27318 if (SCHARS (elt) > 0
27319 && (!NILP (props) || risky))
27320 {
27321 Lisp_Object oprops, aelt;
27322 oprops = Ftext_properties_at (make_fixnum (0), elt);
27323
27324
27325
27326
27327
27328 if (NILP (Fequal (props, oprops)) || risky)
27329 {
27330
27331
27332 if (! NILP (oprops) && !risky)
27333 {
27334 Lisp_Object tem;
27335
27336 oprops = Fcopy_sequence (oprops);
27337 tem = props;
27338 while (CONSP (tem))
27339 {
27340 oprops = plist_put (oprops, XCAR (tem),
27341 XCAR (XCDR (tem)));
27342 tem = XCDR (XCDR (tem));
27343 }
27344 props = oprops;
27345 }
27346
27347 aelt = Fassoc (elt, mode_line_proptrans_alist, Qnil);
27348 if (! NILP (aelt) && !NILP (Fequal (props, XCDR (aelt))))
27349 {
27350
27351
27352 elt = XCAR (aelt);
27353 mode_line_proptrans_alist
27354 = move_elt_to_front (aelt, mode_line_proptrans_alist);
27355 }
27356 else
27357 {
27358 Lisp_Object tem;
27359
27360
27361
27362 if (! NILP (aelt))
27363 mode_line_proptrans_alist
27364 = Fdelq (aelt, mode_line_proptrans_alist);
27365
27366 elt = Fcopy_sequence (elt);
27367
27368
27369
27370 internal_condition_case_n (safe_set_text_properties,
27371 4,
27372 ((Lisp_Object [])
27373 {make_fixnum (0),
27374 Flength (elt),
27375 props,
27376 elt}),
27377 Qt, safe_eval_handler);
27378
27379 mode_line_proptrans_alist
27380 = Fcons (Fcons (elt, props),
27381 mode_line_proptrans_alist);
27382
27383
27384 tem = Fnthcdr (make_fixnum (50),
27385 mode_line_proptrans_alist);
27386 if (! NILP (tem))
27387 XSETCDR (tem, Qnil);
27388 }
27389 }
27390 }
27391
27392 offset = 0;
27393
27394 if (literal)
27395 {
27396 prec = precision - n;
27397 switch (mode_line_target)
27398 {
27399 case MODE_LINE_NOPROP:
27400 case MODE_LINE_TITLE:
27401 n += store_mode_line_noprop (SSDATA (elt), -1, prec);
27402 break;
27403 case MODE_LINE_STRING:
27404 n += store_mode_line_string (NULL, elt, true, 0, prec, Qnil);
27405 break;
27406 case MODE_LINE_DISPLAY:
27407 n += display_string (NULL, elt, Qnil, 0, 0, it,
27408 0, prec, 0, STRING_MULTIBYTE (elt));
27409 break;
27410 }
27411
27412 break;
27413 }
27414
27415
27416
27417 while ((precision <= 0 || n < precision)
27418 && SREF (elt, offset) != 0
27419 && (mode_line_target != MODE_LINE_DISPLAY
27420 || it->current_x < it->last_visible_x))
27421 {
27422 ptrdiff_t last_offset = offset;
27423
27424
27425 while ((c = SREF (elt, offset++)) != '\0' && c != '%')
27426 ;
27427
27428 if (offset - 1 != last_offset)
27429 {
27430 ptrdiff_t nchars, nbytes;
27431
27432
27433
27434
27435 offset--;
27436
27437 prec = c_string_width (SDATA (elt) + last_offset,
27438 offset - last_offset, precision - n,
27439 &nchars, &nbytes);
27440
27441 switch (mode_line_target)
27442 {
27443 case MODE_LINE_NOPROP:
27444 case MODE_LINE_TITLE:
27445 n += store_mode_line_noprop (SSDATA (elt) + last_offset, 0, prec);
27446 break;
27447 case MODE_LINE_STRING:
27448 {
27449 ptrdiff_t bytepos = last_offset;
27450 ptrdiff_t charpos = string_byte_to_char (elt, bytepos);
27451 ptrdiff_t endpos = (precision <= 0
27452 ? string_byte_to_char (elt, offset)
27453 : charpos + nchars);
27454 Lisp_Object mode_string
27455 = Fsubstring (elt, make_fixnum (charpos),
27456 make_fixnum (endpos));
27457 n += store_mode_line_string (NULL, mode_string, false,
27458 0, 0, Qnil);
27459 }
27460 break;
27461 case MODE_LINE_DISPLAY:
27462 {
27463 ptrdiff_t bytepos = last_offset;
27464 ptrdiff_t charpos = string_byte_to_char (elt, bytepos);
27465
27466 if (precision <= 0)
27467 nchars = string_byte_to_char (elt, offset) - charpos;
27468 n += display_string (NULL, elt, Qnil, 0, charpos,
27469 it, 0, nchars, 0,
27470 STRING_MULTIBYTE (elt));
27471 }
27472 break;
27473 }
27474 }
27475 else
27476 {
27477 ptrdiff_t percent_position = offset;
27478
27479
27480
27481 field = 0;
27482 while ((c = SREF (elt, offset++)) >= '0' && c <= '9')
27483 field = field * 10 + c - '0';
27484
27485
27486 if (field_width - n > 0 && field > field_width - n)
27487 field = field_width - n;
27488
27489
27490 prec = precision - n;
27491
27492 if (c == 'M')
27493 n += display_mode_element (it, depth, field, prec,
27494 Vglobal_mode_string, props,
27495 risky);
27496 else if (c != 0)
27497 {
27498 bool multibyte;
27499 ptrdiff_t bytepos, charpos;
27500 const char *spec;
27501 Lisp_Object string;
27502
27503 bytepos = percent_position;
27504 charpos = (STRING_MULTIBYTE (elt)
27505 ? string_byte_to_char (elt, bytepos)
27506 : bytepos);
27507 spec = decode_mode_spec (it->w, c, field, &string);
27508 eassert (NILP (string) || STRINGP (string));
27509 multibyte = !NILP (string) && STRING_MULTIBYTE (string);
27510
27511
27512 ptrdiff_t nbytes = strlen (spec);
27513 ptrdiff_t nchars, mb_nbytes;
27514 parse_str_as_multibyte ((const unsigned char *)spec, nbytes,
27515 &nchars, &mb_nbytes);
27516 if (!(nbytes == nchars || nbytes != mb_nbytes))
27517 multibyte = true;
27518
27519 switch (mode_line_target)
27520 {
27521 case MODE_LINE_NOPROP:
27522 case MODE_LINE_TITLE:
27523 n += store_mode_line_noprop (spec, field, prec);
27524 break;
27525 case MODE_LINE_STRING:
27526 {
27527 Lisp_Object tem = build_string (spec);
27528 props = Ftext_properties_at (make_fixnum (charpos), elt);
27529
27530 n += store_mode_line_string (NULL, tem, false,
27531 field, prec, props);
27532 }
27533 break;
27534 case MODE_LINE_DISPLAY:
27535 {
27536 int nglyphs_before, nwritten;
27537
27538 nglyphs_before = it->glyph_row->used[TEXT_AREA];
27539 nwritten = display_string (spec, string, elt,
27540 charpos, 0, it,
27541 field, prec, 0,
27542 multibyte);
27543
27544
27545
27546
27547 if (nwritten > 0)
27548 {
27549 struct glyph *glyph
27550 = (it->glyph_row->glyphs[TEXT_AREA]
27551 + nglyphs_before);
27552 int i;
27553
27554 for (i = 0; i < nwritten; ++i)
27555 {
27556 glyph[i].object = elt;
27557 glyph[i].charpos = charpos;
27558 }
27559
27560 n += nwritten;
27561 }
27562 }
27563 break;
27564 }
27565 }
27566 else
27567 break;
27568 }
27569 }
27570 }
27571 break;
27572
27573 case Lisp_Symbol:
27574
27575
27576
27577
27578 {
27579 register Lisp_Object tem;
27580
27581
27582
27583 if (NILP (Fget (elt, Qrisky_local_variable)))
27584 risky = true;
27585
27586 tem = Fboundp (elt);
27587 if (!NILP (tem))
27588 {
27589 tem = Fsymbol_value (elt);
27590
27591
27592 if (STRINGP (tem))
27593 literal = true;
27594
27595 if (!EQ (tem, elt))
27596 {
27597
27598 elt = tem;
27599 goto tail_recurse;
27600 }
27601 }
27602 }
27603 break;
27604
27605 case Lisp_Cons:
27606 {
27607 register Lisp_Object car, tem;
27608
27609
27610
27611
27612
27613
27614
27615
27616
27617
27618 car = XCAR (elt);
27619 if (EQ (car, QCeval))
27620 {
27621
27622
27623
27624 if (risky)
27625 break;
27626
27627 if (CONSP (XCDR (elt)))
27628 {
27629 Lisp_Object spec;
27630 spec = safe__eval (true, XCAR (XCDR (elt)));
27631
27632
27633
27634
27635
27636
27637 if (!FRAME_LIVE_P (it->f))
27638 signal_error (":eval deleted the frame being displayed", elt);
27639 n += display_mode_element (it, depth, field_width - n,
27640 precision - n, spec, props,
27641 risky);
27642 }
27643 }
27644 else if (EQ (car, QCpropertize))
27645 {
27646
27647
27648
27649 if (risky)
27650 break;
27651
27652 if (CONSP (XCDR (elt)))
27653 n += display_mode_element (it, depth, field_width - n,
27654 precision - n, XCAR (XCDR (elt)),
27655 XCDR (XCDR (elt)), risky);
27656 }
27657 else if (SYMBOLP (car))
27658 {
27659 tem = Fboundp (car);
27660 elt = XCDR (elt);
27661 if (!CONSP (elt))
27662 goto invalid;
27663
27664
27665 if (!NILP (tem))
27666 {
27667 tem = Fsymbol_value (car);
27668 if (!NILP (tem))
27669 {
27670 elt = XCAR (elt);
27671 goto tail_recurse;
27672 }
27673 }
27674
27675
27676
27677 elt = XCDR (elt);
27678 if (NILP (elt))
27679 break;
27680 else if (!CONSP (elt))
27681 goto invalid;
27682 elt = XCAR (elt);
27683 goto tail_recurse;
27684 }
27685 else if (FIXNUMP (car))
27686 {
27687 register int lim = XFIXNUM (car);
27688 elt = XCDR (elt);
27689 if (lim < 0)
27690 {
27691
27692 if (precision <= 0)
27693 precision = -lim;
27694 else
27695 precision = min (precision, -lim);
27696 }
27697 else if (lim > 0)
27698 {
27699
27700
27701 if (precision > 0)
27702 lim = min (precision, lim);
27703
27704
27705
27706
27707 field_width = max (lim, field_width);
27708 }
27709 goto tail_recurse;
27710 }
27711 else if (STRINGP (car) || CONSP (car))
27712 FOR_EACH_TAIL_SAFE (elt)
27713 {
27714 if (0 < precision && precision <= n)
27715 break;
27716 n += display_mode_element (it, depth,
27717
27718
27719 (! CONSP (XCDR (elt))
27720 ? field_width - n
27721 : 0),
27722 precision - n, XCAR (elt),
27723 props, risky);
27724 }
27725 }
27726 break;
27727
27728 default:
27729 invalid:
27730 elt = build_string ("*invalid*");
27731 goto tail_recurse;
27732 }
27733
27734
27735 if (field_width > 0 && n < field_width)
27736 {
27737 switch (mode_line_target)
27738 {
27739 case MODE_LINE_NOPROP:
27740 case MODE_LINE_TITLE:
27741 n += store_mode_line_noprop ("", field_width - n, 0);
27742 break;
27743 case MODE_LINE_STRING:
27744 n += store_mode_line_string ("", Qnil, false, field_width - n, 0,
27745 Qnil);
27746 break;
27747 case MODE_LINE_DISPLAY:
27748 n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
27749 0, 0, 0);
27750 break;
27751 }
27752 }
27753
27754 return n;
27755 }
27756
27757
27758
27759
27760
27761
27762
27763
27764
27765
27766
27767
27768
27769
27770
27771
27772
27773
27774
27775
27776 static int
27777 store_mode_line_string (const char *string, Lisp_Object lisp_string,
27778 bool copy_string,
27779 int field_width, int precision, Lisp_Object props)
27780 {
27781 ptrdiff_t len;
27782 int n = 0;
27783
27784 if (string != NULL)
27785 {
27786 len = strnlen (string, precision <= 0 ? SIZE_MAX : precision);
27787 lisp_string = make_string (string, len);
27788 if (NILP (props))
27789 props = mode_line_string_face_prop;
27790 else if (!NILP (mode_line_string_face))
27791 {
27792 Lisp_Object face = plist_get (props, Qface);
27793 props = Fcopy_sequence (props);
27794 if (NILP (face))
27795 face = mode_line_string_face;
27796 else
27797 face = list2 (face, mode_line_string_face);
27798 props = plist_put (props, Qface, face);
27799 }
27800 Fadd_text_properties (make_fixnum (0), make_fixnum (len),
27801 props, lisp_string);
27802 }
27803 else
27804 {
27805 len = SCHARS (lisp_string);
27806 if (precision > 0 && len > precision)
27807 {
27808 len = precision;
27809 lisp_string = Fsubstring (lisp_string, make_fixnum (0), make_fixnum (len));
27810 precision = -1;
27811 }
27812 if (!NILP (mode_line_string_face))
27813 {
27814 Lisp_Object face;
27815 if (NILP (props))
27816 props = Ftext_properties_at (make_fixnum (0), lisp_string);
27817 face = plist_get (props, Qface);
27818 if (NILP (face))
27819 face = mode_line_string_face;
27820 else
27821 face = list2 (face, mode_line_string_face);
27822 props = list2 (Qface, face);
27823 if (copy_string)
27824 lisp_string = Fcopy_sequence (lisp_string);
27825 }
27826 if (!NILP (props))
27827 Fadd_text_properties (make_fixnum (0), make_fixnum (len),
27828 props, lisp_string);
27829 }
27830
27831 if (len > 0)
27832 {
27833 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
27834 n += len;
27835 }
27836
27837 if (field_width > len)
27838 {
27839 field_width -= len;
27840 lisp_string = Fmake_string (make_fixnum (field_width), make_fixnum (' '),
27841 Qnil);
27842 if (!NILP (props))
27843 Fadd_text_properties (make_fixnum (0), make_fixnum (field_width),
27844 props, lisp_string);
27845 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
27846 n += field_width;
27847 }
27848
27849 return n;
27850 }
27851
27852
27853 DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line,
27854 1, 4, 0,
27855 doc:
27856
27857
27858
27859
27860
27861
27862
27863
27864
27865
27866
27867
27868
27869
27870
27871 )
27872 (Lisp_Object format, Lisp_Object face,
27873 Lisp_Object window, Lisp_Object buffer)
27874 {
27875 struct it it;
27876 int len;
27877 struct window *w;
27878 struct buffer *old_buffer = NULL;
27879 int face_id;
27880 bool no_props = FIXNUMP (face);
27881 specpdl_ref count = SPECPDL_INDEX ();
27882 Lisp_Object str;
27883 int string_start = 0;
27884
27885 w = decode_any_window (window);
27886 XSETWINDOW (window, w);
27887
27888 if (NILP (buffer))
27889 buffer = w->contents;
27890 CHECK_BUFFER (buffer);
27891
27892
27893
27894 if (NILP (format) || noninteractive)
27895 return empty_unibyte_string;
27896
27897 if (no_props)
27898 face = Qnil;
27899
27900 face_id = (NILP (face) || EQ (face, Qdefault)) ? DEFAULT_FACE_ID
27901 : EQ (face, Qt) ? (EQ (window, selected_window)
27902 ? MODE_LINE_ACTIVE_FACE_ID : MODE_LINE_INACTIVE_FACE_ID)
27903 : EQ (face, Qmode_line_active) ? MODE_LINE_ACTIVE_FACE_ID
27904 : EQ (face, Qmode_line_inactive) ? MODE_LINE_INACTIVE_FACE_ID
27905 : EQ (face, Qheader_line) ? HEADER_LINE_FACE_ID
27906 : EQ (face, Qtab_line) ? TAB_LINE_FACE_ID
27907 : EQ (face, Qtab_bar) ? TAB_BAR_FACE_ID
27908 : EQ (face, Qtool_bar) ? TOOL_BAR_FACE_ID
27909 : DEFAULT_FACE_ID;
27910
27911 old_buffer = current_buffer;
27912
27913
27914
27915 record_unwind_protect (unwind_format_mode_line,
27916 format_mode_line_unwind_data
27917 (XFRAME (WINDOW_FRAME (w)),
27918 old_buffer, selected_window, true));
27919 mode_line_proptrans_alist = Qnil;
27920
27921 Fselect_window (window, Qt);
27922 set_buffer_internal_1 (XBUFFER (buffer));
27923
27924 init_iterator (&it, w, -1, -1, NULL, face_id);
27925
27926 if (no_props)
27927 {
27928 mode_line_target = MODE_LINE_NOPROP;
27929 mode_line_string_face_prop = Qnil;
27930 mode_line_string_list = Qnil;
27931 string_start = MODE_LINE_NOPROP_LEN (0);
27932 }
27933 else
27934 {
27935 mode_line_target = MODE_LINE_STRING;
27936 mode_line_string_list = Qnil;
27937 mode_line_string_face = face;
27938 mode_line_string_face_prop
27939 = NILP (face) ? Qnil : list2 (Qface, face);
27940 }
27941
27942 push_kboard (FRAME_KBOARD (it.f));
27943 display_mode_element (&it, 0, 0, 0, format, Qnil, false);
27944 pop_kboard ();
27945
27946 if (no_props)
27947 {
27948 len = MODE_LINE_NOPROP_LEN (string_start);
27949 str = make_string (mode_line_noprop_buf + string_start, len);
27950 }
27951 else
27952 {
27953 mode_line_string_list = Fnreverse (mode_line_string_list);
27954 str = Fmapconcat (Qidentity, mode_line_string_list,
27955 empty_unibyte_string);
27956 }
27957
27958 return unbind_to (count, str);
27959 }
27960
27961
27962
27963
27964 static void
27965 pint2str (register char *buf, register int width, register ptrdiff_t d)
27966 {
27967 register char *p = buf;
27968
27969 if (d <= 0)
27970 *p++ = '0';
27971 else
27972 {
27973 while (d > 0)
27974 {
27975 *p++ = d % 10 + '0';
27976 d /= 10;
27977 }
27978 }
27979
27980 for (width -= (int) (p - buf); width > 0; --width)
27981 *p++ = ' ';
27982 *p-- = '\0';
27983 while (p > buf)
27984 {
27985 d = *buf;
27986 *buf++ = *p;
27987 *p-- = d;
27988 }
27989 }
27990
27991
27992
27993
27994
27995 static const char power_letter[] =
27996 {
27997 0,
27998 'k',
27999 'M',
28000 'G',
28001 'T',
28002 'P',
28003 'E',
28004 'Z',
28005 'Y',
28006 'R',
28007 'Q'
28008 };
28009
28010 static void
28011 pint2hrstr (char *buf, int width, ptrdiff_t d)
28012 {
28013
28014
28015 ptrdiff_t quotient = d;
28016 int remainder = 0;
28017
28018 int tenths = -1;
28019 int exponent = 0;
28020
28021
28022 int length;
28023
28024 char * psuffix;
28025 char * p;
28026
28027 if (quotient >= 1000)
28028 {
28029
28030 do
28031 {
28032 remainder = quotient % 1000;
28033 quotient /= 1000;
28034 exponent++;
28035 }
28036 while (quotient >= 1000);
28037
28038
28039 if (quotient <= 9)
28040 {
28041 tenths = remainder / 100;
28042 if (remainder % 100 >= 50)
28043 {
28044 if (tenths < 9)
28045 tenths++;
28046 else
28047 {
28048 quotient++;
28049 if (quotient == 10)
28050 tenths = -1;
28051 else
28052 tenths = 0;
28053 }
28054 }
28055 }
28056 else
28057 if (remainder >= 500)
28058 {
28059 if (quotient < 999)
28060 quotient++;
28061 else
28062 {
28063 quotient = 1;
28064 exponent++;
28065 tenths = 0;
28066 }
28067 }
28068 }
28069
28070
28071 if (tenths == -1 && quotient <= 99)
28072 if (quotient <= 9)
28073 length = 1;
28074 else
28075 length = 2;
28076 else
28077 length = 3;
28078 p = psuffix = buf + max (width, length);
28079
28080
28081 *psuffix++ = power_letter[exponent];
28082 *psuffix = '\0';
28083
28084
28085 if (tenths >= 0)
28086 {
28087 *--p = '0' + tenths;
28088 *--p = '.';
28089 }
28090
28091
28092 do
28093 {
28094 int digit = quotient % 10;
28095 *--p = '0' + digit;
28096 }
28097 while ((quotient /= 10) != 0);
28098
28099
28100 while (buf < p)
28101 *--p = ' ';
28102 }
28103
28104
28105
28106
28107
28108 static unsigned char invalid_eol_type[] = "(*invalid*)";
28109
28110 static char *
28111 decode_mode_spec_coding (Lisp_Object coding_system, char *buf, bool eol_flag)
28112 {
28113 Lisp_Object val;
28114 bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
28115 const unsigned char *eol_str;
28116 int eol_str_len;
28117
28118 Lisp_Object eoltype;
28119
28120 val = CODING_SYSTEM_SPEC (coding_system);
28121 eoltype = Qnil;
28122
28123 if (!VECTORP (val))
28124 {
28125 *buf++ = multibyte ? '-' : ' ';
28126 if (eol_flag)
28127 eoltype = eol_mnemonic_undecided;
28128
28129 }
28130 else
28131 {
28132 Lisp_Object attrs;
28133 Lisp_Object eolvalue;
28134
28135 attrs = AREF (val, 0);
28136 eolvalue = AREF (val, 2);
28137
28138 if (multibyte)
28139 buf += CHAR_STRING (XFIXNAT (CODING_ATTR_MNEMONIC (attrs)),
28140 (unsigned char *) buf);
28141 else
28142 *buf++ = ' ';
28143
28144 if (eol_flag)
28145 {
28146
28147
28148 if (NILP (eolvalue))
28149 eoltype = eol_mnemonic_undecided;
28150 else if (VECTORP (eolvalue))
28151 eoltype = eol_mnemonic_undecided;
28152 else
28153 eoltype = (EQ (eolvalue, Qunix)
28154 ? eol_mnemonic_unix
28155 : EQ (eolvalue, Qdos)
28156 ? eol_mnemonic_dos : eol_mnemonic_mac);
28157 }
28158 }
28159
28160 if (eol_flag)
28161 {
28162
28163 if (STRINGP (eoltype))
28164 {
28165 eol_str = SDATA (eoltype);
28166 eol_str_len = SBYTES (eoltype);
28167 }
28168 else if (CHARACTERP (eoltype))
28169 {
28170 int c = XFIXNAT (eoltype);
28171 return buf + CHAR_STRING (c, (unsigned char *) buf);
28172 }
28173 else
28174 {
28175 eol_str = invalid_eol_type;
28176 eol_str_len = sizeof (invalid_eol_type) - 1;
28177 }
28178 memcpy (buf, eol_str, eol_str_len);
28179 buf += eol_str_len;
28180 }
28181
28182 return buf;
28183 }
28184
28185
28186
28187
28188 static int
28189 percent99 (ptrdiff_t n, ptrdiff_t d)
28190 {
28191 int percent = (d - 1 + 100.0 * n) / d;
28192 return min (percent, 99);
28193 }
28194
28195
28196
28197
28198
28199
28200
28201
28202
28203 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
28204
28205 static const char *
28206 decode_mode_spec (struct window *w, register int c, int field_width,
28207 Lisp_Object *string)
28208 {
28209 Lisp_Object obj;
28210 struct frame *f = XFRAME (WINDOW_FRAME (w));
28211 char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
28212
28213
28214
28215
28216
28217 int width = min (field_width, FRAME_MESSAGE_BUF_SIZE (f));
28218 struct buffer *b = current_buffer;
28219
28220 obj = Qnil;
28221 *string = Qnil;
28222
28223 switch (c)
28224 {
28225 case '*':
28226 if (!NILP (BVAR (b, read_only)))
28227 return "%";
28228 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28229 return "*";
28230 return "-";
28231
28232 case '+':
28233
28234 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28235 return "*";
28236 if (!NILP (BVAR (b, read_only)))
28237 return "%";
28238 return "-";
28239
28240 case '&':
28241
28242 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28243 return "*";
28244 return "-";
28245
28246 case '%':
28247 return "%";
28248
28249 case '[':
28250 {
28251 int i;
28252 char *p;
28253
28254 if (command_loop_level > 5)
28255 return "[[[... ";
28256 p = decode_mode_spec_buf;
28257 for (i = 0; i < command_loop_level; i++)
28258 *p++ = '[';
28259 *p = 0;
28260 return decode_mode_spec_buf;
28261 }
28262
28263 case ']':
28264 {
28265 int i;
28266 char *p;
28267
28268 if (command_loop_level > 5)
28269 return " ...]]]";
28270 p = decode_mode_spec_buf;
28271 for (i = 0; i < command_loop_level; i++)
28272 *p++ = ']';
28273 *p = 0;
28274 return decode_mode_spec_buf;
28275 }
28276
28277 case '-':
28278 {
28279 register int i;
28280
28281
28282 if (mode_line_target == MODE_LINE_NOPROP
28283 || mode_line_target == MODE_LINE_STRING)
28284 return "--";
28285 if (field_width <= 0
28286 || field_width > sizeof (lots_of_dashes))
28287 {
28288 for (i = 0; i < FRAME_MESSAGE_BUF_SIZE (f) - 1; ++i)
28289 decode_mode_spec_buf[i] = '-';
28290 decode_mode_spec_buf[i] = '\0';
28291 return decode_mode_spec_buf;
28292 }
28293 else
28294 return lots_of_dashes;
28295 }
28296
28297 case 'b':
28298 obj = BVAR (b, name);
28299 break;
28300
28301 case 'c':
28302 case 'C':
28303
28304
28305
28306
28307
28308 if (mode_line_target == MODE_LINE_TITLE)
28309 return "";
28310 else
28311 {
28312 ptrdiff_t col = current_column ();
28313 int disp_col = (c == 'C') ? col + 1 : col;
28314 w->column_number_displayed = col;
28315 pint2str (decode_mode_spec_buf, width, disp_col);
28316 return decode_mode_spec_buf;
28317 }
28318
28319 case 'e':
28320 #if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
28321 {
28322 if (NILP (Vmemory_full))
28323 return "";
28324 else
28325 return "!MEM FULL! ";
28326 }
28327 #else
28328 return "";
28329 #endif
28330
28331 case 'F':
28332
28333 if (!NILP (f->title))
28334 return SSDATA (f->title);
28335 if (f->explicit_name || ! FRAME_WINDOW_P (f))
28336 return SSDATA (f->name);
28337 return "Emacs";
28338
28339 case 'f':
28340 obj = BVAR (b, filename);
28341 break;
28342
28343 case 'i':
28344 {
28345 ptrdiff_t size = ZV - BEGV;
28346 pint2str (decode_mode_spec_buf, width, size);
28347 return decode_mode_spec_buf;
28348 }
28349
28350 case 'I':
28351 {
28352 ptrdiff_t size = ZV - BEGV;
28353 pint2hrstr (decode_mode_spec_buf, width, size);
28354 return decode_mode_spec_buf;
28355 }
28356
28357 case 'l':
28358 {
28359 ptrdiff_t startpos, startpos_byte, line, linepos, linepos_byte;
28360 ptrdiff_t topline, nlines, height;
28361 ptrdiff_t junk;
28362
28363
28364 if (mode_line_target == MODE_LINE_TITLE)
28365 return "";
28366
28367 startpos = marker_position (w->start);
28368 startpos_byte = marker_byte_position (w->start);
28369 height = WINDOW_TOTAL_LINES (w);
28370
28371
28372
28373
28374
28375
28376
28377
28378 if (!(BUF_BEGV_BYTE (b) <= startpos_byte
28379 && startpos_byte <= BUF_ZV_BYTE (b)))
28380 {
28381 startpos = BUF_BEGV (b);
28382 startpos_byte = BUF_BEGV_BYTE (b);
28383 w->base_line_pos = 0;
28384 w->base_line_number = 0;
28385 }
28386
28387
28388
28389 if (w->base_line_pos == -1)
28390 goto no_value;
28391
28392
28393 if (FIXNUMP (Vline_number_display_limit)
28394 && BUF_ZV (b) - BUF_BEGV (b) > XFIXNUM (Vline_number_display_limit))
28395 {
28396 w->base_line_pos = 0;
28397 w->base_line_number = 0;
28398 goto no_value;
28399 }
28400
28401 if (w->base_line_number > 0
28402 && w->base_line_pos > 0
28403 && w->base_line_pos <= startpos)
28404 {
28405 line = w->base_line_number;
28406 linepos = w->base_line_pos;
28407 linepos_byte = buf_charpos_to_bytepos (b, linepos);
28408 }
28409 else
28410 {
28411 line = 1;
28412 linepos = BUF_BEGV (b);
28413 linepos_byte = BUF_BEGV_BYTE (b);
28414 }
28415
28416
28417 nlines = display_count_lines (linepos_byte,
28418 startpos_byte,
28419 startpos, &junk);
28420
28421 topline = nlines + line;
28422
28423
28424
28425
28426
28427 if (startpos == BUF_BEGV (b))
28428 {
28429 w->base_line_number = topline;
28430 w->base_line_pos = BUF_BEGV (b);
28431 }
28432 else if (nlines < height + 25 || nlines > height * 3 + 50
28433 || linepos == BUF_BEGV (b))
28434 {
28435 ptrdiff_t limit = BUF_BEGV (b);
28436 ptrdiff_t limit_byte = BUF_BEGV_BYTE (b);
28437 ptrdiff_t position;
28438 ptrdiff_t distance
28439 = (line_number_display_limit_width < 0 ? 0
28440 : ckd_mul (&distance, line_number_display_limit_width,
28441 height * 2 + 30)
28442 ? PTRDIFF_MAX : distance);
28443
28444 if (startpos - distance > limit)
28445 {
28446 limit = startpos - distance;
28447 limit_byte = CHAR_TO_BYTE (limit);
28448 }
28449
28450 nlines = display_count_lines (startpos_byte,
28451 limit_byte,
28452 - (height * 2 + 30),
28453 &position);
28454
28455
28456
28457 if (position == limit_byte && limit == startpos - distance)
28458 {
28459 w->base_line_pos = -1;
28460 w->base_line_number = 0;
28461 goto no_value;
28462 }
28463
28464 w->base_line_number = topline - nlines;
28465 w->base_line_pos = BYTE_TO_CHAR (position);
28466 }
28467
28468
28469 nlines = display_count_lines (startpos_byte,
28470 PT_BYTE, PT, &junk);
28471
28472
28473 line_number_displayed = true;
28474
28475
28476 pint2str (decode_mode_spec_buf, width, topline + nlines);
28477 return decode_mode_spec_buf;
28478 no_value:
28479 {
28480 char *p = decode_mode_spec_buf;
28481 int pad = width - 2;
28482 while (pad-- > 0)
28483 *p++ = ' ';
28484 *p++ = '?';
28485 *p++ = '?';
28486 *p = '\0';
28487 return decode_mode_spec_buf;
28488 }
28489 }
28490 break;
28491
28492 case 'm':
28493 obj = BVAR (b, mode_name);
28494 break;
28495
28496 case 'n':
28497 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
28498 return " Narrow";
28499 break;
28500
28501
28502 case 'o':
28503 {
28504 ptrdiff_t toppos = marker_position (w->start);
28505 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28506 ptrdiff_t begv = BUF_BEGV (b);
28507 ptrdiff_t zv = BUF_ZV (b);
28508
28509 if (zv <= botpos)
28510 return toppos <= begv ? "All" : "Bottom";
28511 else if (toppos <= begv)
28512 return "Top";
28513 else
28514 {
28515 sprintf (decode_mode_spec_buf, "%2d%%",
28516 percent99 (toppos - begv, (toppos - begv) + (zv - botpos)));
28517 return decode_mode_spec_buf;
28518 }
28519 }
28520
28521
28522 case 'p':
28523 {
28524 ptrdiff_t pos = marker_position (w->start);
28525 ptrdiff_t begv = BUF_BEGV (b);
28526 ptrdiff_t zv = BUF_ZV (b);
28527
28528 if (w->window_end_pos <= BUF_Z (b) - zv)
28529 return pos <= begv ? "All" : "Bottom";
28530 else if (pos <= begv)
28531 return "Top";
28532 else
28533 {
28534 sprintf (decode_mode_spec_buf, "%2d%%",
28535 percent99 (pos - begv, zv - begv));
28536 return decode_mode_spec_buf;
28537 }
28538 }
28539
28540
28541 case 'P':
28542 {
28543 ptrdiff_t toppos = marker_position (w->start);
28544 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28545 ptrdiff_t begv = BUF_BEGV (b);
28546 ptrdiff_t zv = BUF_ZV (b);
28547
28548 if (zv <= botpos)
28549 return toppos <= begv ? "All" : "Bottom";
28550 else
28551 {
28552 sprintf (decode_mode_spec_buf,
28553 &"Top%2d%%"[begv < toppos ? sizeof "Top" - 1 : 0],
28554 percent99 (botpos - begv, zv - begv));
28555 return decode_mode_spec_buf;
28556 }
28557 }
28558
28559
28560
28561 case 'q':
28562 {
28563 ptrdiff_t toppos = marker_position (w->start);
28564 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28565 ptrdiff_t begv = BUF_BEGV (b);
28566 ptrdiff_t zv = BUF_ZV (b);
28567 int top_perc, bot_perc;
28568
28569 if ((toppos <= begv) && (zv <= botpos))
28570 return "All ";
28571
28572 top_perc = toppos <= begv ? 0 : percent99 (toppos - begv, zv - begv);
28573 bot_perc = zv <= botpos ? 100 : percent99 (botpos - begv, zv - begv);
28574
28575 if (top_perc == bot_perc)
28576 sprintf (decode_mode_spec_buf, "%d%%", top_perc);
28577 else
28578 sprintf (decode_mode_spec_buf, "%d-%d%%", top_perc, bot_perc);
28579
28580 return decode_mode_spec_buf;
28581 }
28582
28583 case 's':
28584
28585 obj = Fget_buffer_process (Fcurrent_buffer ());
28586 if (NILP (obj))
28587 return "no process";
28588 #ifndef MSDOS
28589 obj = Fsymbol_name (Fprocess_status (obj));
28590 #endif
28591 break;
28592
28593 case '@':
28594 {
28595 specpdl_ref count = inhibit_garbage_collection ();
28596 Lisp_Object curdir = BVAR (current_buffer, directory);
28597 Lisp_Object val = Qnil;
28598
28599 if (STRINGP (curdir))
28600 val = safe_call1 (intern ("file-remote-p"), curdir);
28601
28602 val = unbind_to (count, val);
28603
28604 if (NILP (val))
28605 return "-";
28606 else
28607 return "@";
28608 }
28609
28610 case 'z':
28611
28612 case 'Z':
28613
28614 {
28615 bool eol_flag = (c == 'Z');
28616 char *p = decode_mode_spec_buf;
28617
28618 if (! FRAME_WINDOW_P (f))
28619 {
28620
28621
28622 p = decode_mode_spec_coding (CODING_ID_NAME
28623 (FRAME_KEYBOARD_CODING (f)->id),
28624 p, false);
28625 p = decode_mode_spec_coding (CODING_ID_NAME
28626 (FRAME_TERMINAL_CODING (f)->id),
28627 p, false);
28628 }
28629 p = decode_mode_spec_coding (BVAR (b, buffer_file_coding_system),
28630 p, eol_flag);
28631
28632 #if false
28633 #ifdef subprocesses
28634 obj = Fget_buffer_process (Fcurrent_buffer ());
28635 if (PROCESSP (obj))
28636 {
28637 p = decode_mode_spec_coding
28638 (XPROCESS (obj)->decode_coding_system, p, eol_flag);
28639 p = decode_mode_spec_coding
28640 (XPROCESS (obj)->encode_coding_system, p, eol_flag);
28641 }
28642 #endif
28643 #endif
28644 *p = 0;
28645 return decode_mode_spec_buf;
28646 }
28647 }
28648
28649 if (STRINGP (obj))
28650 {
28651 *string = obj;
28652 return SSDATA (obj);
28653 }
28654 else
28655 return "";
28656 }
28657
28658
28659
28660
28661 ptrdiff_t
28662 count_lines (ptrdiff_t start_byte, ptrdiff_t end_byte)
28663 {
28664 ptrdiff_t ignored;
28665 return display_count_lines (start_byte, end_byte, ZV, &ignored);
28666 }
28667
28668
28669
28670
28671
28672
28673
28674
28675
28676
28677
28678 static ptrdiff_t
28679 display_count_lines (ptrdiff_t start_byte,
28680 ptrdiff_t limit_byte, ptrdiff_t count,
28681 ptrdiff_t *byte_pos_ptr)
28682 {
28683 register unsigned char *cursor;
28684 unsigned char *base;
28685
28686 register ptrdiff_t ceiling;
28687 register unsigned char *ceiling_addr;
28688 ptrdiff_t orig_count = count;
28689
28690
28691
28692 bool selective_display
28693 = (!NILP (BVAR (current_buffer, selective_display))
28694 && !FIXNUMP (BVAR (current_buffer, selective_display)));
28695
28696 if (count > 0)
28697 {
28698 while (start_byte < limit_byte)
28699 {
28700 ceiling = BUFFER_CEILING_OF (start_byte);
28701 ceiling = min (limit_byte - 1, ceiling);
28702 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
28703 base = (cursor = BYTE_POS_ADDR (start_byte));
28704
28705 do
28706 {
28707 if (selective_display)
28708 {
28709 while (*cursor != '\n' && *cursor != 015
28710 && ++cursor != ceiling_addr)
28711 continue;
28712 if (cursor == ceiling_addr)
28713 break;
28714 }
28715 else
28716 {
28717 cursor = memchr (cursor, '\n', ceiling_addr - cursor);
28718 if (! cursor)
28719 break;
28720 }
28721
28722 cursor++;
28723
28724 if (--count == 0)
28725 {
28726 start_byte += cursor - base;
28727 *byte_pos_ptr = start_byte;
28728 return orig_count;
28729 }
28730 }
28731 while (cursor < ceiling_addr);
28732
28733 start_byte += ceiling_addr - base;
28734 }
28735 }
28736 else
28737 {
28738 while (start_byte > limit_byte)
28739 {
28740 ceiling = BUFFER_FLOOR_OF (start_byte - 1);
28741 ceiling = max (limit_byte, ceiling);
28742 ceiling_addr = BYTE_POS_ADDR (ceiling);
28743 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
28744 while (true)
28745 {
28746 if (selective_display)
28747 {
28748 while (--cursor >= ceiling_addr
28749 && *cursor != '\n' && *cursor != 015)
28750 continue;
28751 if (cursor < ceiling_addr)
28752 break;
28753 }
28754 else
28755 {
28756 cursor = memrchr (ceiling_addr, '\n', cursor - ceiling_addr);
28757 if (! cursor)
28758 break;
28759 }
28760
28761 if (++count == 0)
28762 {
28763 start_byte += cursor - base + 1;
28764 *byte_pos_ptr = start_byte;
28765
28766
28767 return - orig_count - 1;
28768 }
28769 }
28770 start_byte += ceiling_addr - base;
28771 }
28772 }
28773
28774 *byte_pos_ptr = limit_byte;
28775
28776 if (count < 0)
28777 return - orig_count + count;
28778 return orig_count - count;
28779
28780 }
28781
28782
28783
28784
28785
28786
28787
28788
28789
28790
28791
28792
28793
28794
28795
28796
28797
28798
28799
28800
28801
28802
28803
28804
28805
28806
28807
28808
28809
28810
28811
28812
28813
28814
28815
28816
28817
28818
28819
28820
28821
28822
28823
28824
28825
28826 static int
28827 display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_string,
28828 ptrdiff_t face_string_pos, ptrdiff_t start, struct it *it,
28829 int field_width, int precision, int max_x, int multibyte)
28830 {
28831 int hpos_at_start = it->hpos;
28832 int saved_face_id = it->face_id;
28833 struct glyph_row *row = it->glyph_row;
28834 ptrdiff_t it_charpos;
28835
28836
28837
28838 reseat_to_string (it, NILP (lisp_string) ? string : NULL, lisp_string,
28839 start, precision, field_width, multibyte);
28840
28841 if (string && STRINGP (lisp_string))
28842
28843
28844 it->stop_charpos = it->end_charpos;
28845
28846
28847
28848 if (STRINGP (face_string))
28849 {
28850 ptrdiff_t endptr;
28851 struct face *face;
28852
28853 it->face_id
28854 = face_at_string_position (it->w, face_string, face_string_pos,
28855 0, &endptr, it->base_face_id, false, 0);
28856 face = FACE_FROM_ID (it->f, it->face_id);
28857 it->face_box_p = face->box != FACE_NO_BOX;
28858
28859
28860
28861
28862 if (NILP (lisp_string))
28863 {
28864 Lisp_Object display = Fget_text_property (make_fixnum (0), Qdisplay,
28865 face_string);
28866 if (!NILP (display))
28867 {
28868 Lisp_Object min_width = plist_get (display, Qmin_width);
28869 if (!NILP (min_width))
28870 display_min_width (it, 0, face_string, min_width);
28871 }
28872 }
28873 }
28874
28875
28876
28877 if (max_x <= 0)
28878 max_x = it->last_visible_x;
28879 else
28880 max_x = min (max_x, it->last_visible_x);
28881
28882
28883
28884 if (it->current_x < it->first_visible_x)
28885 move_it_in_display_line_to (it, 100000, it->first_visible_x,
28886 MOVE_TO_POS | MOVE_TO_X);
28887
28888 row->ascent = it->max_ascent;
28889 row->height = it->max_ascent + it->max_descent;
28890 row->phys_ascent = it->max_phys_ascent;
28891 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
28892 row->extra_line_spacing = it->max_extra_line_spacing;
28893
28894 if (STRINGP (it->string))
28895 it_charpos = IT_STRING_CHARPOS (*it);
28896 else
28897 it_charpos = IT_CHARPOS (*it);
28898
28899
28900
28901 while (it->current_x < max_x)
28902 {
28903 int x_before, x, n_glyphs_before, i, nglyphs;
28904
28905
28906 if (!get_next_display_element (it))
28907 break;
28908
28909
28910 x_before = it->current_x;
28911 n_glyphs_before = row->used[TEXT_AREA];
28912 PRODUCE_GLYPHS (it);
28913
28914 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
28915 i = 0;
28916 x = x_before;
28917 while (i < nglyphs)
28918 {
28919 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
28920
28921 if (it->line_wrap != TRUNCATE
28922 && x + glyph->pixel_width > max_x)
28923 {
28924
28925 if (CHAR_GLYPH_PADDING_P (*glyph))
28926 {
28927
28928 if (row->reversed_p)
28929 unproduce_glyphs (it, row->used[TEXT_AREA]
28930 - n_glyphs_before);
28931 row->used[TEXT_AREA] = n_glyphs_before;
28932 it->current_x = x_before;
28933 }
28934 else
28935 {
28936 if (row->reversed_p)
28937 unproduce_glyphs (it, row->used[TEXT_AREA]
28938 - (n_glyphs_before + i));
28939 row->used[TEXT_AREA] = n_glyphs_before + i;
28940 it->current_x = x;
28941 }
28942 break;
28943 }
28944 else if (x + glyph->pixel_width >= it->first_visible_x)
28945 {
28946
28947 ++it->hpos;
28948 if (x < it->first_visible_x)
28949 row->x = x - it->first_visible_x;
28950 }
28951 else
28952 {
28953
28954
28955 emacs_abort ();
28956 }
28957
28958 row->ascent = max (row->ascent, it->max_ascent);
28959 row->height = max (row->height, it->max_ascent + it->max_descent);
28960 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
28961 row->phys_height = max (row->phys_height,
28962 it->max_phys_ascent + it->max_phys_descent);
28963 row->extra_line_spacing = max (row->extra_line_spacing,
28964 it->max_extra_line_spacing);
28965 x += glyph->pixel_width;
28966 ++i;
28967 }
28968
28969
28970 if (i < nglyphs)
28971 break;
28972
28973
28974 if (ITERATOR_AT_END_OF_LINE_P (it))
28975 {
28976 it->continuation_lines_width = 0;
28977 break;
28978 }
28979
28980 set_iterator_to_next (it, true);
28981 if (STRINGP (it->string))
28982 it_charpos = IT_STRING_CHARPOS (*it);
28983 else
28984 it_charpos = IT_CHARPOS (*it);
28985
28986
28987 if (it->line_wrap == TRUNCATE
28988 && it->current_x >= it->last_visible_x)
28989 {
28990
28991
28992
28993
28994
28995
28996 if (it_charpos <= it->string_nchars)
28997 {
28998 if (!FRAME_WINDOW_P (it->f))
28999 {
29000 int ii, n;
29001
29002 if (it->current_x > it->last_visible_x)
29003 {
29004
29005
29006 bool mode_line_p = false;
29007
29008
29009
29010 if (row->mode_line_p)
29011 {
29012 struct window *w = it->w;
29013 if (row == MATRIX_MODE_LINE_ROW (w->desired_matrix))
29014 mode_line_p = true;
29015 }
29016 if (!row->reversed_p)
29017 {
29018 for (ii = row->used[TEXT_AREA] - 1; ii > 0; --ii)
29019 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii]))
29020 break;
29021 }
29022 else
29023 {
29024 for (ii = 0; ii < row->used[TEXT_AREA]; ii++)
29025 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii]))
29026 break;
29027 unproduce_glyphs (it, ii + 1);
29028 ii = row->used[TEXT_AREA] - (ii + 1);
29029 }
29030 for (n = row->used[TEXT_AREA]; ii < n; ++ii)
29031 {
29032 row->used[TEXT_AREA] = ii;
29033 if (row->mode_line_p)
29034 pad_mode_line (it, mode_line_p);
29035 else
29036 produce_special_glyphs (it, IT_TRUNCATION);
29037 }
29038 }
29039 produce_special_glyphs (it, IT_TRUNCATION);
29040 }
29041 row->truncated_on_right_p = true;
29042 }
29043 break;
29044 }
29045 }
29046
29047
29048 if (it->first_visible_x
29049 && it_charpos > 0)
29050 {
29051 if (!FRAME_WINDOW_P (it->f)
29052 || (row->reversed_p
29053 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
29054 : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
29055 insert_left_trunc_glyphs (it);
29056 row->truncated_on_left_p = true;
29057 }
29058
29059 it->face_id = saved_face_id;
29060
29061
29062 return it->hpos - hpos_at_start;
29063 }
29064
29065
29066
29067
29068
29069
29070
29071
29072
29073
29074
29075 int
29076 invisible_prop (Lisp_Object propval, Lisp_Object list)
29077 {
29078 Lisp_Object tail, proptail;
29079
29080 for (tail = list; CONSP (tail); tail = XCDR (tail))
29081 {
29082 register Lisp_Object tem;
29083 tem = XCAR (tail);
29084 if (EQ (propval, tem))
29085 return 1;
29086 if (CONSP (tem) && EQ (propval, XCAR (tem)))
29087 return NILP (XCDR (tem)) ? 1 : 2;
29088 }
29089
29090 if (CONSP (propval))
29091 {
29092 for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
29093 {
29094 Lisp_Object propelt;
29095 propelt = XCAR (proptail);
29096 for (tail = list; CONSP (tail); tail = XCDR (tail))
29097 {
29098 register Lisp_Object tem;
29099 tem = XCAR (tail);
29100 if (EQ (propelt, tem))
29101 return 1;
29102 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
29103 return NILP (XCDR (tem)) ? 1 : 2;
29104 }
29105 }
29106 }
29107
29108 return 0;
29109 }
29110
29111 DEFUN ("invisible-p", Finvisible_p, Sinvisible_p, 1, 1, 0,
29112 doc:
29113
29114
29115
29116
29117
29118
29119
29120
29121
29122
29123
29124 )
29125 (Lisp_Object pos)
29126 {
29127 Lisp_Object prop
29128 = (FIXNATP (pos) || MARKERP (pos)
29129 ? Fget_char_property (pos, Qinvisible, Qnil)
29130 : pos);
29131 int invis = TEXT_PROP_MEANS_INVISIBLE (prop);
29132 return (invis == 0 ? Qnil
29133 : invis == 1 ? Qt
29134 : make_fixnum (invis));
29135 }
29136
29137
29138
29139
29140
29141
29142
29143
29144
29145
29146
29147
29148
29149
29150
29151
29152
29153
29154
29155
29156
29157
29158
29159
29160
29161
29162
29163
29164
29165
29166
29167
29168
29169
29170
29171
29172
29173
29174
29175
29176
29177
29178
29179
29180
29181
29182
29183
29184
29185
29186
29187
29188
29189
29190
29191
29192
29193
29194
29195
29196
29197
29198
29199
29200
29201
29202
29203
29204
29205
29206
29207
29208
29209
29210
29211
29212
29213
29214
29215
29216
29217 static bool
29218 calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
29219 struct font *font, bool width_p, int *align_to)
29220 {
29221
29222
29223
29224
29225 int lnum_pixel_width = it->line_number_produced_p ? it->lnum_pixel_width : 0;
29226 double pixels;
29227
29228 # define OK_PIXELS(val) (*res = (val), true)
29229 # define OK_ALIGN_TO(val) (*align_to = (val), true)
29230
29231 if (NILP (prop))
29232 return OK_PIXELS (0);
29233
29234 eassert (FRAME_LIVE_P (it->f));
29235
29236 if (SYMBOLP (prop))
29237 {
29238 if (SCHARS (SYMBOL_NAME (prop)) == 2)
29239 {
29240 char *unit = SSDATA (SYMBOL_NAME (prop));
29241
29242
29243 if (unit[0] == 'i' && unit[1] == 'n')
29244 pixels = 1.0;
29245 else if (unit[0] == 'm' && unit[1] == 'm')
29246 pixels = 25.4;
29247 else if (unit[0] == 'c' && unit[1] == 'm')
29248 pixels = 2.54;
29249 else
29250 pixels = 0;
29251 if (pixels > 0)
29252 {
29253 double ppi = (width_p ? FRAME_RES_X (it->f)
29254 : FRAME_RES_Y (it->f));
29255
29256 if (ppi > 0)
29257 return OK_PIXELS (ppi / pixels);
29258 return false;
29259 }
29260 }
29261
29262 #ifdef HAVE_WINDOW_SYSTEM
29263
29264 if (EQ (prop, Qheight))
29265 return OK_PIXELS (font
29266 ? normal_char_height (font, -1)
29267 : FRAME_LINE_HEIGHT (it->f));
29268
29269 if (EQ (prop, Qwidth))
29270 return OK_PIXELS (font
29271 ? FONT_WIDTH (font)
29272 : FRAME_COLUMN_WIDTH (it->f));
29273 #else
29274 if (EQ (prop, Qheight) || EQ (prop, Qwidth))
29275 return OK_PIXELS (1);
29276 #endif
29277
29278
29279 if (EQ (prop, Qtext))
29280 return OK_PIXELS (width_p
29281 ? (window_box_width (it->w, TEXT_AREA)
29282 - lnum_pixel_width)
29283 : WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w));
29284
29285
29286
29287
29288 if (align_to && *align_to < 0)
29289 {
29290 *res = 0;
29291
29292 if (EQ (prop, Qleft))
29293 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
29294 + lnum_pixel_width);
29295
29296 if (EQ (prop, Qright))
29297 return OK_ALIGN_TO (window_box_right_offset (it->w, TEXT_AREA));
29298
29299 if (EQ (prop, Qcenter))
29300 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
29301 + lnum_pixel_width
29302 + window_box_width (it->w, TEXT_AREA) / 2);
29303
29304 if (EQ (prop, Qleft_fringe))
29305 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29306 ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (it->w)
29307 : window_box_right_offset (it->w, LEFT_MARGIN_AREA));
29308
29309 if (EQ (prop, Qright_fringe))
29310 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29311 ? window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
29312 : window_box_right_offset (it->w, TEXT_AREA));
29313
29314 if (EQ (prop, Qleft_margin))
29315 return OK_ALIGN_TO (window_box_left_offset (it->w, LEFT_MARGIN_AREA));
29316
29317 if (EQ (prop, Qright_margin))
29318 return OK_ALIGN_TO (window_box_left_offset (it->w, RIGHT_MARGIN_AREA));
29319
29320 if (EQ (prop, Qscroll_bar))
29321 return OK_ALIGN_TO (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (it->w)
29322 ? 0
29323 : (window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
29324 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29325 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
29326 : 0)));
29327 }
29328 else
29329 {
29330
29331 if (EQ (prop, Qleft_fringe))
29332 return OK_PIXELS (WINDOW_LEFT_FRINGE_WIDTH (it->w));
29333 if (EQ (prop, Qright_fringe))
29334 return OK_PIXELS (WINDOW_RIGHT_FRINGE_WIDTH (it->w));
29335 if (EQ (prop, Qleft_margin))
29336 return OK_PIXELS (WINDOW_LEFT_MARGIN_WIDTH (it->w));
29337 if (EQ (prop, Qright_margin))
29338 return OK_PIXELS (WINDOW_RIGHT_MARGIN_WIDTH (it->w));
29339 if (EQ (prop, Qscroll_bar))
29340 return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
29341 }
29342
29343 prop = buffer_local_value (prop, it->w->contents);
29344 if (BASE_EQ (prop, Qunbound))
29345 prop = Qnil;
29346 }
29347
29348 if (NUMBERP (prop))
29349 {
29350 int base_unit = (width_p
29351 ? FRAME_COLUMN_WIDTH (it->f)
29352 : FRAME_LINE_HEIGHT (it->f));
29353 if (width_p && align_to && *align_to < 0)
29354 return OK_PIXELS (XFLOATINT (prop) * base_unit + lnum_pixel_width);
29355 return OK_PIXELS (XFLOATINT (prop) * base_unit);
29356 }
29357
29358 if (CONSP (prop))
29359 {
29360 Lisp_Object car = XCAR (prop);
29361 Lisp_Object cdr = XCDR (prop);
29362
29363 if (SYMBOLP (car))
29364 {
29365 #ifdef HAVE_WINDOW_SYSTEM
29366
29367 if (FRAME_WINDOW_P (it->f)
29368 && valid_image_p (prop))
29369 {
29370 ptrdiff_t id = lookup_image (it->f, prop, it->face_id);
29371 struct image *img = IMAGE_FROM_ID (it->f, id);
29372
29373 return OK_PIXELS (width_p ? img->width : img->height);
29374 }
29375
29376 if (FRAME_WINDOW_P (it->f) && valid_xwidget_spec_p (prop))
29377 {
29378
29379 return OK_PIXELS (100);
29380 }
29381 #endif
29382
29383
29384 if (EQ (car, Qplus) || EQ (car, Qminus))
29385 {
29386 bool first = true;
29387 double px;
29388
29389 pixels = 0;
29390 while (CONSP (cdr))
29391 {
29392 if (!calc_pixel_width_or_height (&px, it, XCAR (cdr),
29393 font, width_p, align_to))
29394 return false;
29395 if (first)
29396 pixels = (EQ (car, Qplus) ? px : -px), first = false;
29397 else
29398 pixels += px;
29399 cdr = XCDR (cdr);
29400 }
29401 if (EQ (car, Qminus))
29402 pixels = -pixels;
29403 return OK_PIXELS (pixels);
29404 }
29405
29406 car = buffer_local_value (car, it->w->contents);
29407 if (BASE_EQ (car, Qunbound))
29408 car = Qnil;
29409 }
29410
29411
29412 if (NUMBERP (car))
29413 {
29414 double fact;
29415 int offset =
29416 width_p && align_to && *align_to < 0 ? lnum_pixel_width : 0;
29417 pixels = XFLOATINT (car);
29418 if (NILP (cdr))
29419 return OK_PIXELS (pixels + offset);
29420 if (calc_pixel_width_or_height (&fact, it, cdr,
29421 font, width_p, align_to))
29422 return OK_PIXELS (pixels * fact + offset);
29423 return false;
29424 }
29425
29426 return false;
29427 }
29428
29429 return false;
29430 }
29431
29432 void
29433 get_font_ascent_descent (struct font *font, int *ascent, int *descent)
29434 {
29435 #ifdef HAVE_WINDOW_SYSTEM
29436 normal_char_ascent_descent (font, -1, ascent, descent);
29437 #else
29438 *ascent = 1;
29439 *descent = 0;
29440 #endif
29441 }
29442
29443
29444
29445
29446
29447
29448 #ifdef HAVE_WINDOW_SYSTEM
29449
29450 #ifdef GLYPH_DEBUG
29451
29452 extern void dump_glyph_string (struct glyph_string *) EXTERNALLY_VISIBLE;
29453 void
29454 dump_glyph_string (struct glyph_string *s)
29455 {
29456 fputs ("glyph string\n", stderr);
29457 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
29458 s->x, s->y, s->width, s->height);
29459 fprintf (stderr, " ybase = %d\n", s->ybase);
29460 fprintf (stderr, " hl = %u\n", s->hl);
29461 fprintf (stderr, " left overhang = %d, right = %d\n",
29462 s->left_overhang, s->right_overhang);
29463 fprintf (stderr, " nchars = %d\n", s->nchars);
29464 fprintf (stderr, " extends to end of line = %d\n",
29465 s->extends_to_end_of_line_p);
29466 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
29467 fprintf (stderr, " bg width = %d\n", s->background_width);
29468 }
29469
29470 #endif
29471
29472
29473
29474
29475
29476
29477
29478
29479
29480 #ifdef HAVE_NTGUI
29481
29482
29483
29484
29485
29486 # define ALLOCATE_HDC(hdc, f) \
29487 Lisp_Object prev_quit = Vinhibit_quit; \
29488 Vinhibit_quit = Qt; \
29489 HDC hdc = get_frame_dc ((f))
29490 # define RELEASE_HDC(hdc, f) \
29491 release_frame_dc ((f), (hdc)); \
29492 Vinhibit_quit = prev_quit
29493 #else
29494 # define ALLOCATE_HDC(hdc, f)
29495 # define RELEASE_HDC(hdc, f)
29496 #endif
29497
29498 static void
29499 init_glyph_string (struct glyph_string *s,
29500 #ifdef HAVE_NTGUI
29501 HDC hdc,
29502 #endif
29503 unsigned *char2b, struct window *w, struct glyph_row *row,
29504 enum glyph_row_area area, int start, enum draw_glyphs_face hl)
29505 {
29506 memset (s, 0, sizeof *s);
29507 s->w = w;
29508 s->f = XFRAME (w->frame);
29509 #ifdef HAVE_NTGUI
29510 s->hdc = hdc;
29511 #endif
29512 s->char2b = char2b;
29513 s->hl = hl;
29514 s->row = row;
29515 s->area = area;
29516 s->first_glyph = row->glyphs[area] + start;
29517 s->height = row->height;
29518 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
29519 s->ybase = s->y + row->ascent;
29520 }
29521
29522
29523
29524
29525
29526 static void
29527 append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
29528 struct glyph_string *h, struct glyph_string *t)
29529 {
29530 if (h)
29531 {
29532 if (*head)
29533 (*tail)->next = h;
29534 else
29535 *head = h;
29536 h->prev = *tail;
29537 *tail = t;
29538 }
29539 }
29540
29541
29542
29543
29544
29545
29546 static void
29547 prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
29548 struct glyph_string *h, struct glyph_string *t)
29549 {
29550 if (h)
29551 {
29552 if (*head)
29553 (*head)->prev = t;
29554 else
29555 *tail = t;
29556 t->next = *head;
29557 *head = h;
29558 }
29559 }
29560
29561
29562
29563
29564
29565 static void
29566 append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
29567 struct glyph_string *s)
29568 {
29569 s->next = s->prev = NULL;
29570 append_glyph_string_lists (head, tail, s, s);
29571 }
29572
29573
29574
29575
29576
29577
29578
29579
29580 static struct face *
29581 get_char_face_and_encoding (struct frame *f, int c, int face_id,
29582 unsigned *char2b, bool display_p)
29583 {
29584 struct face *face = FACE_FROM_ID (f, face_id);
29585 unsigned code = 0;
29586
29587 if (face->font)
29588 {
29589 code = face->font->driver->encode_char (face->font, c);
29590
29591 if (code == FONT_INVALID_CODE)
29592 code = 0;
29593 }
29594
29595 *char2b = code & 0xFFFF;
29596
29597
29598 #ifdef HAVE_X_WINDOWS
29599 if (display_p)
29600 #endif
29601 {
29602 eassert (face != NULL);
29603 prepare_face_for_display (f, face);
29604 }
29605
29606 return face;
29607 }
29608
29609
29610
29611
29612
29613
29614 static struct face *
29615 get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
29616 unsigned *char2b)
29617 {
29618 struct face *face;
29619 unsigned code = 0;
29620
29621 eassert (glyph->type == CHAR_GLYPH);
29622 face = FACE_FROM_ID (f, glyph->face_id);
29623
29624
29625 prepare_face_for_display (f, face);
29626
29627 if (face->font)
29628 {
29629 if (CHAR_BYTE8_P (glyph->u.ch))
29630 code = CHAR_TO_BYTE8 (glyph->u.ch);
29631 else
29632 code = face->font->driver->encode_char (face->font, glyph->u.ch);
29633
29634 if (code == FONT_INVALID_CODE)
29635 code = 0;
29636 }
29637
29638
29639 *char2b = code & 0xFFFF;
29640 return face;
29641 }
29642
29643
29644
29645
29646
29647 static bool
29648 get_char_glyph_code (int c, struct font *font, unsigned *char2b)
29649 {
29650 unsigned code;
29651
29652 if (CHAR_BYTE8_P (c))
29653 code = CHAR_TO_BYTE8 (c);
29654 else
29655 code = font->driver->encode_char (font, c);
29656
29657 if (code == FONT_INVALID_CODE)
29658 return false;
29659
29660
29661 *char2b = code & 0xFFFF;
29662 return true;
29663 }
29664
29665
29666
29667
29668
29669
29670
29671
29672
29673
29674
29675
29676 static int
29677 fill_composite_glyph_string (struct glyph_string *s, struct face *base_face,
29678 int overlaps)
29679 {
29680 int i;
29681
29682
29683
29684 struct face *face;
29685
29686 eassert (s);
29687
29688 s->for_overlaps = overlaps;
29689 s->face = NULL;
29690 s->font = NULL;
29691 for (i = s->cmp_from; i < s->cmp->glyph_len; i++)
29692 {
29693 int c = COMPOSITION_GLYPH (s->cmp, i);
29694
29695
29696
29697 if (c != '\t')
29698 {
29699 int face_id = FACE_FOR_CHAR (s->f, base_face->ascii_face, c,
29700 -1, Qnil);
29701
29702 face = get_char_face_and_encoding (s->f, c, face_id,
29703 s->char2b + i, true);
29704 if (face)
29705 {
29706 if (! s->face)
29707 {
29708 s->face = face;
29709 s->font = s->face->font;
29710 }
29711 else if (s->face != face)
29712 break;
29713 }
29714 }
29715 ++s->nchars;
29716 }
29717 s->cmp_to = i;
29718
29719 if (s->face == NULL)
29720 {
29721 s->face = base_face->ascii_face;
29722 s->font = s->face->font;
29723 }
29724
29725 if (s->hl == DRAW_MOUSE_FACE
29726 || (s->hl == DRAW_CURSOR
29727 && MATRIX_ROW (s->w->current_matrix,
29728 s->w->phys_cursor.vpos)->mouse_face_p
29729 && cursor_in_mouse_face_p (s->w)))
29730 {
29731 int c = COMPOSITION_GLYPH (s->cmp, 0);
29732 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29733 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29734 if (!s->face)
29735 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29736
29737 s->face = FACE_FROM_ID (s->f, FACE_FOR_CHAR (s->f, s->face, c, -1, Qnil));
29738 prepare_face_for_display (s->f, s->face);
29739 }
29740
29741
29742
29743 s->width = s->first_glyph->pixel_width;
29744
29745
29746
29747
29748
29749 if (s->font == NULL)
29750 {
29751 s->font_not_found_p = true;
29752 s->font = FRAME_FONT (s->f);
29753 }
29754
29755
29756 s->ybase += s->first_glyph->voffset;
29757
29758 return s->cmp_to;
29759 }
29760
29761 static int
29762 fill_gstring_glyph_string (struct glyph_string *s, int face_id,
29763 int start, int end, int overlaps)
29764 {
29765 struct glyph *glyph, *last;
29766 int voffset;
29767 Lisp_Object lgstring;
29768 int i;
29769 bool glyph_not_available_p;
29770
29771 s->for_overlaps = overlaps;
29772 glyph = s->row->glyphs[s->area] + start;
29773 last = s->row->glyphs[s->area] + end;
29774 voffset = glyph->voffset;
29775 glyph_not_available_p = glyph->glyph_not_available_p;
29776 s->cmp_id = glyph->u.cmp.id;
29777 s->cmp_from = glyph->slice.cmp.from;
29778 s->cmp_to = glyph->slice.cmp.to + 1;
29779 if (s->hl == DRAW_MOUSE_FACE
29780 || (s->hl == DRAW_CURSOR
29781 && MATRIX_ROW (s->w->current_matrix,
29782 s->w->phys_cursor.vpos)->mouse_face_p
29783 && cursor_in_mouse_face_p (s->w)))
29784 {
29785 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29786 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29787 if (!s->face)
29788 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29789 prepare_face_for_display (s->f, s->face);
29790 }
29791 else
29792 s->face = FACE_FROM_ID (s->f, face_id);
29793 lgstring = composition_gstring_from_id (s->cmp_id);
29794 s->font = XFONT_OBJECT (LGSTRING_FONT (lgstring));
29795
29796
29797 s->width = s->first_glyph->pixel_width;
29798 glyph++;
29799 while (glyph < last
29800 && glyph->u.cmp.automatic
29801 && glyph->u.cmp.id == s->cmp_id
29802 && glyph->face_id == face_id
29803 && s->cmp_to == glyph->slice.cmp.from
29804 && glyph->glyph_not_available_p == glyph_not_available_p)
29805 {
29806 s->width += glyph->pixel_width;
29807 s->cmp_to = (glyph++)->slice.cmp.to + 1;
29808 }
29809
29810 for (i = s->cmp_from; i < s->cmp_to; i++)
29811 {
29812 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
29813 unsigned code = LGLYPH_CODE (lglyph);
29814
29815
29816 s->char2b[i] = code & 0xFFFF;
29817 }
29818
29819
29820
29821
29822 if (glyph_not_available_p)
29823 s->font_not_found_p = true;
29824
29825
29826 s->ybase += voffset;
29827
29828 return glyph - s->row->glyphs[s->area];
29829 }
29830
29831
29832
29833
29834
29835
29836
29837 static int
29838 fill_glyphless_glyph_string (struct glyph_string *s, int face_id,
29839 int start, int end, int overlaps)
29840 {
29841 struct glyph *glyph, *last;
29842 int voffset;
29843
29844 eassert (s->first_glyph->type == GLYPHLESS_GLYPH);
29845 s->for_overlaps = overlaps;
29846 glyph = s->row->glyphs[s->area] + start;
29847 last = s->row->glyphs[s->area] + end;
29848 voffset = glyph->voffset;
29849 s->face = FACE_FROM_ID (s->f, face_id);
29850 s->font = s->face->font ? s->face->font : FRAME_FONT (s->f);
29851 if (s->hl == DRAW_MOUSE_FACE
29852 || (s->hl == DRAW_CURSOR
29853 && MATRIX_ROW (s->w->current_matrix,
29854 s->w->phys_cursor.vpos)->mouse_face_p
29855 && cursor_in_mouse_face_p (s->w)))
29856 {
29857 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29858 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29859 if (!s->face)
29860 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29861 prepare_face_for_display (s->f, s->face);
29862 }
29863 s->nchars = 1;
29864 s->width = glyph->pixel_width;
29865 glyph++;
29866 while (glyph < last
29867 && glyph->type == GLYPHLESS_GLYPH
29868 && glyph->voffset == voffset
29869 && glyph->face_id == face_id)
29870 {
29871 s->nchars++;
29872 s->width += glyph->pixel_width;
29873 glyph++;
29874 }
29875 s->ybase += voffset;
29876 return glyph - s->row->glyphs[s->area];
29877 }
29878
29879
29880
29881
29882
29883
29884
29885
29886
29887
29888
29889 static int
29890 fill_glyph_string (struct glyph_string *s, int face_id,
29891 int start, int end, int overlaps)
29892 {
29893 struct glyph *glyph, *last;
29894 int voffset;
29895 bool glyph_not_available_p;
29896
29897 eassert (s->f == XFRAME (s->w->frame));
29898 eassert (s->nchars == 0);
29899 eassert (start >= 0 && end > start);
29900
29901 s->for_overlaps = overlaps;
29902 glyph = s->row->glyphs[s->area] + start;
29903 last = s->row->glyphs[s->area] + end;
29904 voffset = glyph->voffset;
29905 s->padding_p = glyph->padding_p;
29906 glyph_not_available_p = glyph->glyph_not_available_p;
29907
29908 while (glyph < last
29909 && glyph->type == CHAR_GLYPH
29910 && glyph->voffset == voffset
29911
29912 && glyph->face_id == face_id
29913 && glyph->glyph_not_available_p == glyph_not_available_p)
29914 {
29915 s->face = get_glyph_face_and_encoding (s->f, glyph,
29916 s->char2b + s->nchars);
29917 ++s->nchars;
29918 eassert (s->nchars <= end - start);
29919 s->width += glyph->pixel_width;
29920 if (glyph++->padding_p != s->padding_p)
29921 break;
29922 }
29923
29924 s->font = s->face->font;
29925
29926 if (s->hl == DRAW_MOUSE_FACE
29927 || (s->hl == DRAW_CURSOR
29928 && MATRIX_ROW (s->w->current_matrix,
29929 s->w->phys_cursor.vpos)->mouse_face_p
29930 && cursor_in_mouse_face_p (s->w)))
29931 {
29932 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29933 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29934 if (!s->face)
29935 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29936 s->face
29937 = FACE_FROM_ID (s->f, FACE_FOR_CHAR (s->f, s->face,
29938 s->first_glyph->u.ch, -1, Qnil));
29939 prepare_face_for_display (s->f, s->face);
29940 }
29941
29942
29943
29944
29945
29946 if (s->font == NULL || glyph_not_available_p)
29947 {
29948 s->font_not_found_p = true;
29949 s->font = FRAME_FONT (s->f);
29950 }
29951
29952
29953 s->ybase += voffset;
29954
29955 eassert (s->face && s->face->gc);
29956 return glyph - s->row->glyphs[s->area];
29957 }
29958
29959
29960
29961
29962 static void
29963 fill_image_glyph_string (struct glyph_string *s)
29964 {
29965 eassert (s->first_glyph->type == IMAGE_GLYPH);
29966 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
29967 eassert (s->img);
29968 s->slice = s->first_glyph->slice.img;
29969 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
29970 s->font = s->face->font;
29971 if (s->hl == DRAW_MOUSE_FACE
29972 || (s->hl == DRAW_CURSOR
29973 && MATRIX_ROW (s->w->current_matrix,
29974 s->w->phys_cursor.vpos)->mouse_face_p
29975 && cursor_in_mouse_face_p (s->w)))
29976 {
29977 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29978 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29979 if (!s->face)
29980 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29981 prepare_face_for_display (s->f, s->face);
29982 }
29983 s->width = s->first_glyph->pixel_width;
29984
29985
29986 s->ybase += s->first_glyph->voffset;
29987 }
29988
29989
29990 #ifdef HAVE_XWIDGETS
29991 static void
29992 fill_xwidget_glyph_string (struct glyph_string *s)
29993 {
29994 eassert (s->first_glyph->type == XWIDGET_GLYPH);
29995 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
29996 s->font = s->face->font;
29997 if (s->hl == DRAW_MOUSE_FACE
29998 || (s->hl == DRAW_CURSOR
29999 && MATRIX_ROW (s->w->current_matrix,
30000 s->w->phys_cursor.vpos)->mouse_face_p
30001 && cursor_in_mouse_face_p (s->w)))
30002 {
30003 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
30004 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
30005 if (!s->face)
30006 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
30007 prepare_face_for_display (s->f, s->face);
30008 }
30009 s->width = s->first_glyph->pixel_width;
30010 s->ybase += s->first_glyph->voffset;
30011 s->xwidget = xwidget_from_id (s->first_glyph->u.xwidget);
30012 }
30013 #endif
30014
30015
30016
30017
30018
30019
30020
30021 static int
30022 fill_stretch_glyph_string (struct glyph_string *s, int start, int end)
30023 {
30024 struct glyph *glyph, *last;
30025 int voffset, face_id;
30026
30027 eassert (s->first_glyph->type == STRETCH_GLYPH);
30028
30029 glyph = s->row->glyphs[s->area] + start;
30030 last = s->row->glyphs[s->area] + end;
30031 face_id = glyph->face_id;
30032 s->face = FACE_FROM_ID (s->f, face_id);
30033 s->font = s->face->font;
30034 if (s->hl == DRAW_MOUSE_FACE
30035 || (s->hl == DRAW_CURSOR
30036 && MATRIX_ROW (s->w->current_matrix,
30037 s->w->phys_cursor.vpos)->mouse_face_p
30038 && cursor_in_mouse_face_p (s->w)))
30039 {
30040 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
30041 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
30042 if (!s->face)
30043 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
30044 prepare_face_for_display (s->f, s->face);
30045 }
30046 s->width = glyph->pixel_width;
30047 s->nchars = 1;
30048 voffset = glyph->voffset;
30049
30050 for (++glyph;
30051 (glyph < last
30052 && glyph->type == STRETCH_GLYPH
30053 && glyph->voffset == voffset
30054 && glyph->face_id == face_id);
30055 ++glyph)
30056 s->width += glyph->pixel_width;
30057
30058
30059 s->ybase += voffset;
30060
30061
30062
30063 eassert (s->face);
30064 return glyph - s->row->glyphs[s->area];
30065 }
30066
30067 static struct font_metrics *
30068 get_per_char_metric (struct font *font, const unsigned *char2b)
30069 {
30070 static struct font_metrics metrics;
30071
30072 if (! font)
30073 return NULL;
30074 if (*char2b == FONT_INVALID_CODE)
30075 return NULL;
30076
30077 font->driver->text_extents (font, char2b, 1, &metrics);
30078 return &metrics;
30079 }
30080
30081
30082
30083
30084
30085
30086
30087 static void
30088 normal_char_ascent_descent (struct font *font, int c, int *ascent, int *descent)
30089 {
30090 *ascent = FONT_BASE (font);
30091 *descent = FONT_DESCENT (font);
30092
30093 if (FONT_TOO_HIGH (font))
30094 {
30095 unsigned char2b;
30096
30097
30098
30099 if (get_char_glyph_code (c >= 0 ? c : '{', font, &char2b))
30100 {
30101 struct font_metrics *pcm = get_per_char_metric (font, &char2b);
30102 eassume (pcm);
30103
30104 if (!(pcm->width == 0 && pcm->rbearing == 0 && pcm->lbearing == 0))
30105 {
30106
30107
30108
30109 *ascent = pcm->ascent + 1;
30110 *descent = pcm->descent + 1;
30111 }
30112 }
30113 }
30114 }
30115
30116
30117
30118
30119
30120
30121 static int
30122 normal_char_height (struct font *font, int c)
30123 {
30124 int ascent, descent;
30125
30126 normal_char_ascent_descent (font, c, &ascent, &descent);
30127
30128 return ascent + descent;
30129 }
30130
30131
30132
30133
30134
30135
30136 void
30137 gui_get_glyph_overhangs (struct glyph *glyph, struct frame *f, int *left, int *right)
30138 {
30139 *left = *right = 0;
30140
30141 if (glyph->type == CHAR_GLYPH)
30142 {
30143 unsigned char2b;
30144 struct face *face = get_glyph_face_and_encoding (f, glyph, &char2b);
30145 if (face->font)
30146 {
30147 struct font_metrics *pcm = get_per_char_metric (face->font, &char2b);
30148 if (pcm)
30149 {
30150 if (pcm->rbearing > pcm->width)
30151 *right = pcm->rbearing - pcm->width;
30152 if (pcm->lbearing < 0)
30153 *left = -pcm->lbearing;
30154 }
30155 }
30156 }
30157 else if (glyph->type == COMPOSITE_GLYPH)
30158 {
30159 if (! glyph->u.cmp.automatic)
30160 {
30161 struct composition *cmp = composition_table[glyph->u.cmp.id];
30162
30163 if (cmp->rbearing > cmp->pixel_width)
30164 *right = cmp->rbearing - cmp->pixel_width;
30165 if (cmp->lbearing < 0)
30166 *left = - cmp->lbearing;
30167 }
30168 else
30169 {
30170 Lisp_Object gstring = composition_gstring_from_id (glyph->u.cmp.id);
30171 struct font_metrics metrics;
30172
30173 composition_gstring_width (gstring, glyph->slice.cmp.from,
30174 glyph->slice.cmp.to + 1, &metrics);
30175 if (metrics.rbearing > metrics.width)
30176 *right = metrics.rbearing - metrics.width;
30177 if (metrics.lbearing < 0)
30178 *left = - metrics.lbearing;
30179 }
30180 }
30181 }
30182
30183
30184
30185
30186
30187
30188 static int
30189 left_overwritten (struct glyph_string *s)
30190 {
30191 int k;
30192
30193 if (s->left_overhang)
30194 {
30195 int x = 0, i;
30196 struct glyph *glyphs = s->row->glyphs[s->area];
30197 int first = s->first_glyph - glyphs;
30198
30199 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
30200 x -= glyphs[i].pixel_width;
30201
30202 k = i + 1;
30203 }
30204 else
30205 k = -1;
30206
30207 return k;
30208 }
30209
30210
30211
30212
30213
30214
30215 static int
30216 left_overwriting (struct glyph_string *s)
30217 {
30218 int i, k, x;
30219 struct glyph *glyphs = s->row->glyphs[s->area];
30220 int first = s->first_glyph - glyphs;
30221
30222 k = -1;
30223 x = 0;
30224 for (i = first - 1; i >= 0; --i)
30225 {
30226 int left, right;
30227 gui_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
30228 if (x + right > 0)
30229 k = i;
30230 x -= glyphs[i].pixel_width;
30231 }
30232
30233 return k;
30234 }
30235
30236
30237
30238
30239
30240
30241 static int
30242 right_overwritten (struct glyph_string *s)
30243 {
30244 int k = -1;
30245
30246 if (s->right_overhang)
30247 {
30248 int x = 0, i;
30249 struct glyph *glyphs = s->row->glyphs[s->area];
30250 int first = (s->first_glyph - glyphs
30251 + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
30252 int end = s->row->used[s->area];
30253
30254 for (i = first; i < end && s->right_overhang > x; ++i)
30255 x += glyphs[i].pixel_width;
30256
30257 k = i;
30258 }
30259
30260 return k;
30261 }
30262
30263
30264
30265
30266
30267
30268 static int
30269 right_overwriting (struct glyph_string *s)
30270 {
30271 int i, k, x;
30272 int end = s->row->used[s->area];
30273 struct glyph *glyphs = s->row->glyphs[s->area];
30274 int first = (s->first_glyph - glyphs
30275 + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
30276
30277 k = -1;
30278 x = 0;
30279 for (i = first; i < end; ++i)
30280 {
30281 int left, right;
30282 gui_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
30283 if (x - left < 0)
30284 k = i;
30285 x += glyphs[i].pixel_width;
30286 }
30287
30288 return k;
30289 }
30290
30291
30292
30293
30294
30295
30296
30297
30298
30299
30300
30301 static void
30302 set_glyph_string_background_width (struct glyph_string *s, int start, int last_x)
30303 {
30304
30305
30306
30307 if (start == s->row->used[s->area]
30308 && ((s->row->fill_line_p
30309 && (s->hl == DRAW_NORMAL_TEXT
30310 || s->hl == DRAW_IMAGE_RAISED
30311 || s->hl == DRAW_IMAGE_SUNKEN))
30312 || s->hl == DRAW_MOUSE_FACE))
30313 s->extends_to_end_of_line_p = true;
30314
30315
30316
30317
30318 if (s->extends_to_end_of_line_p)
30319 s->background_width = last_x - s->x + 1;
30320 else
30321 {
30322 s->background_width = s->width;
30323 #ifdef HAVE_WINDOW_SYSTEM
30324 if (FRAME_WINDOW_P (s->f)
30325 && s->hl == DRAW_CURSOR
30326 && MATRIX_ROW (s->w->current_matrix,
30327 s->w->phys_cursor.vpos)->mouse_face_p
30328 && cursor_in_mouse_face_p (s->w))
30329 {
30330
30331
30332
30333
30334 struct glyph *g = s->first_glyph;
30335 struct face *regular_face = FACE_FROM_ID (s->f, g->face_id);
30336 s->background_width +=
30337 adjust_glyph_width_for_mouse_face (g, s->row, s->w,
30338 regular_face, s->face);
30339
30340 s->width = s->background_width;
30341 }
30342 #endif
30343 }
30344 }
30345
30346
30347
30348
30349
30350 static struct glyph_string *
30351 glyph_string_containing_background_width (struct glyph_string *s)
30352 {
30353 if (s->cmp)
30354 while (s->cmp_from)
30355 s = s->prev;
30356
30357 return s;
30358 }
30359
30360
30361
30362
30363
30364
30365 static void
30366 compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
30367 {
30368 if (backward_p)
30369 {
30370 while (s)
30371 {
30372 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
30373 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
30374 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
30375 x -= s->width;
30376 s->x = x;
30377 s = s->prev;
30378 }
30379 }
30380 else
30381 {
30382 while (s)
30383 {
30384 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
30385 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
30386 s->x = x;
30387 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
30388 x += s->width;
30389 s = s->next;
30390 }
30391 }
30392 }
30393
30394
30395
30396
30397
30398
30399
30400
30401
30402 #ifdef HAVE_NTGUI
30403
30404
30405 #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
30406 init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
30407 #else
30408 #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
30409 init_glyph_string (s, char2b, w, row, area, start, hl)
30410 #endif
30411
30412
30413
30414
30415
30416
30417
30418
30419
30420
30421
30422 #define BUILD_STRETCH_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30423 do \
30424 { \
30425 s = alloca (sizeof *s); \
30426 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30427 START = fill_stretch_glyph_string (s, START, END); \
30428 append_glyph_string (&HEAD, &TAIL, s); \
30429 s->x = (X); \
30430 } \
30431 while (false)
30432
30433
30434
30435
30436
30437
30438
30439
30440
30441
30442 #define BUILD_IMAGE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30443 do \
30444 { \
30445 s = alloca (sizeof *s); \
30446 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30447 fill_image_glyph_string (s); \
30448 append_glyph_string (&HEAD, &TAIL, s); \
30449 ++START; \
30450 s->x = (X); \
30451 } \
30452 while (false)
30453
30454 #ifndef HAVE_XWIDGETS
30455 # define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30456 eassume (false)
30457 #else
30458 # define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30459 do \
30460 { \
30461 s = alloca (sizeof *s); \
30462 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30463 fill_xwidget_glyph_string (s); \
30464 append_glyph_string (&(HEAD), &(TAIL), s); \
30465 ++(START); \
30466 s->x = (X); \
30467 } \
30468 while (false)
30469 #endif
30470
30471
30472
30473
30474
30475
30476
30477
30478
30479
30480 #define BUILD_CHAR_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
30481 do \
30482 { \
30483 int face_id; \
30484 unsigned *char2b; \
30485 \
30486 face_id = (row)->glyphs[area][START].face_id; \
30487 \
30488 s = alloca (sizeof *s); \
30489 SAFE_NALLOCA (char2b, 1, (END) - (START)); \
30490 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30491 append_glyph_string (&HEAD, &TAIL, s); \
30492 s->x = (X); \
30493 START = fill_glyph_string (s, face_id, START, END, overlaps); \
30494 } \
30495 while (false)
30496
30497
30498
30499
30500
30501
30502
30503
30504
30505
30506
30507 #define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30508 do { \
30509 int face_id = (row)->glyphs[area][START].face_id; \
30510 struct face *base_face = FACE_FROM_ID (f, face_id); \
30511 ptrdiff_t cmp_id = (row)->glyphs[area][START].u.cmp.id; \
30512 struct composition *cmp = composition_table[cmp_id]; \
30513 unsigned *char2b; \
30514 struct glyph_string *first_s = NULL; \
30515 int n; \
30516 \
30517 SAFE_NALLOCA (char2b, 1, cmp->glyph_len); \
30518 \
30519
30520 \
30521 for (n = 0; n < cmp->glyph_len;) \
30522 { \
30523 s = alloca (sizeof *s); \
30524 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30525 append_glyph_string (&(HEAD), &(TAIL), s); \
30526 s->cmp = cmp; \
30527 s->cmp_from = n; \
30528 s->x = (X); \
30529 if (n == 0) \
30530 first_s = s; \
30531 n = fill_composite_glyph_string (s, base_face, overlaps); \
30532 } \
30533 \
30534 ++START; \
30535 s = first_s; \
30536 } while (false)
30537
30538
30539
30540
30541
30542 #define BUILD_GSTRING_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30543 do { \
30544 int face_id; \
30545 unsigned *char2b; \
30546 Lisp_Object gstring; \
30547 \
30548 face_id = (row)->glyphs[area][START].face_id; \
30549 gstring = (composition_gstring_from_id \
30550 ((row)->glyphs[area][START].u.cmp.id)); \
30551 s = alloca (sizeof *s); \
30552 SAFE_NALLOCA (char2b, 1, LGSTRING_GLYPH_LEN (gstring)); \
30553 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30554 append_glyph_string (&(HEAD), &(TAIL), s); \
30555 s->x = (X); \
30556 START = fill_gstring_glyph_string (s, face_id, START, END, overlaps); \
30557 } while (false)
30558
30559
30560
30561
30562
30563
30564 #define BUILD_GLYPHLESS_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30565 do \
30566 { \
30567 int face_id; \
30568 \
30569 face_id = (row)->glyphs[area][START].face_id; \
30570 \
30571 s = alloca (sizeof *s); \
30572 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30573 append_glyph_string (&HEAD, &TAIL, s); \
30574 s->x = (X); \
30575 START = fill_glyphless_glyph_string (s, face_id, START, END, \
30576 overlaps); \
30577 } \
30578 while (false)
30579
30580
30581
30582
30583
30584
30585
30586
30587
30588
30589
30590
30591 #define BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
30592 do \
30593 { \
30594 HEAD = TAIL = NULL; \
30595 while (START < END) \
30596 { \
30597 struct glyph *first_glyph = (row)->glyphs[area] + START; \
30598 switch (first_glyph->type) \
30599 { \
30600 case CHAR_GLYPH: \
30601 BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \
30602 HL, X, LAST_X); \
30603 break; \
30604 \
30605 case COMPOSITE_GLYPH: \
30606 if (first_glyph->u.cmp.automatic) \
30607 BUILD_GSTRING_GLYPH_STRING (START, END, HEAD, TAIL, \
30608 HL, X, LAST_X); \
30609 else \
30610 BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \
30611 HL, X, LAST_X); \
30612 break; \
30613 \
30614 case STRETCH_GLYPH: \
30615 BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \
30616 HL, X, LAST_X); \
30617 break; \
30618 \
30619 case IMAGE_GLYPH: \
30620 BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \
30621 HL, X, LAST_X); \
30622 break;
30623
30624 #define BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
30625 case XWIDGET_GLYPH: \
30626 BUILD_XWIDGET_GLYPH_STRING (START, END, HEAD, TAIL, \
30627 HL, X, LAST_X); \
30628 break;
30629
30630 #define BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X) \
30631 case GLYPHLESS_GLYPH: \
30632 BUILD_GLYPHLESS_GLYPH_STRING (START, END, HEAD, TAIL, \
30633 HL, X, LAST_X); \
30634 break; \
30635 \
30636 default: \
30637 emacs_abort (); \
30638 } \
30639 \
30640 if (s) \
30641 { \
30642 set_glyph_string_background_width (s, START, LAST_X); \
30643 (X) += s->width; \
30644 } \
30645 } \
30646 } while (false)
30647
30648
30649 #define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
30650 BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
30651 BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
30652 BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X)
30653
30654
30655
30656
30657
30658
30659
30660
30661
30662
30663
30664
30665
30666
30667
30668
30669
30670
30671
30672
30673
30674
30675
30676
30677 static int
30678 draw_glyphs (struct window *w, int x, struct glyph_row *row,
30679 enum glyph_row_area area, ptrdiff_t start, ptrdiff_t end,
30680 enum draw_glyphs_face hl, int overlaps)
30681 {
30682 struct glyph_string *head, *tail;
30683 struct glyph_string *s;
30684 struct glyph_string *clip_head = NULL, *clip_tail = NULL;
30685 int i, j, x_reached, last_x, area_left = 0;
30686 struct frame *f = XFRAME (WINDOW_FRAME (w));
30687
30688 ALLOCATE_HDC (hdc, f);
30689
30690
30691 end = min (end, row->used[area]);
30692 start = clip_to_bounds (0, start, end);
30693
30694
30695
30696 if (row->full_width_p)
30697 {
30698
30699
30700 area_left = WINDOW_LEFT_EDGE_X (w);
30701 last_x = (WINDOW_LEFT_EDGE_X (w) + WINDOW_PIXEL_WIDTH (w)
30702 - (row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
30703 }
30704 else
30705 {
30706 area_left = window_box_left (w, area);
30707 last_x = area_left + window_box_width (w, area);
30708 }
30709 x += area_left;
30710
30711
30712
30713
30714
30715 i = start;
30716 USE_SAFE_ALLOCA;
30717 BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x);
30718 if (tail)
30719 {
30720 s = glyph_string_containing_background_width (tail);
30721 x_reached = s->x + s->background_width;
30722 }
30723 else
30724 x_reached = x;
30725
30726
30727
30728
30729 if (head && !overlaps && row->contains_overlapping_glyphs_p)
30730 {
30731 struct glyph_string *h, *t;
30732 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
30733 int mouse_beg_col UNINIT, mouse_end_col UNINIT;
30734 bool check_mouse_face = false;
30735 int dummy_x = 0;
30736
30737
30738
30739 if (area == TEXT_AREA && row->mouse_face_p
30740 && hlinfo->mouse_face_beg_row >= 0
30741 && hlinfo->mouse_face_end_row >= 0)
30742 {
30743 ptrdiff_t row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
30744
30745 if (row_vpos >= hlinfo->mouse_face_beg_row
30746 && row_vpos <= hlinfo->mouse_face_end_row)
30747 {
30748 check_mouse_face = true;
30749 mouse_beg_col = (row_vpos == hlinfo->mouse_face_beg_row)
30750 ? hlinfo->mouse_face_beg_col : 0;
30751 mouse_end_col = (row_vpos == hlinfo->mouse_face_end_row)
30752 ? hlinfo->mouse_face_end_col
30753 : row->used[TEXT_AREA];
30754 }
30755 }
30756
30757
30758 if (FRAME_RIF (f)->compute_glyph_string_overhangs)
30759 for (s = head; s; s = s->next)
30760 FRAME_RIF (f)->compute_glyph_string_overhangs (s);
30761
30762
30763
30764
30765
30766
30767 i = left_overwritten (head);
30768 if (i >= 0)
30769 {
30770 enum draw_glyphs_face overlap_hl;
30771
30772
30773
30774
30775
30776
30777
30778
30779 if (check_mouse_face
30780 && mouse_beg_col < start && mouse_end_col > i)
30781 overlap_hl = DRAW_MOUSE_FACE;
30782 else
30783 overlap_hl = DRAW_NORMAL_TEXT;
30784
30785 if (hl != overlap_hl)
30786 clip_head = head;
30787 j = i;
30788 BUILD_GLYPH_STRINGS (j, start, h, t,
30789 overlap_hl, dummy_x, last_x);
30790 start = i;
30791 compute_overhangs_and_x (t, head->x, true);
30792 prepend_glyph_string_lists (&head, &tail, h, t);
30793 if (clip_head == NULL)
30794 clip_head = head;
30795 }
30796
30797
30798
30799
30800
30801
30802
30803
30804 i = left_overwriting (head);
30805 if (i >= 0)
30806 {
30807 enum draw_glyphs_face overlap_hl;
30808
30809 if (check_mouse_face
30810 && mouse_beg_col < start && mouse_end_col > i)
30811 overlap_hl = DRAW_MOUSE_FACE;
30812 else
30813 overlap_hl = DRAW_NORMAL_TEXT;
30814
30815 if (hl == overlap_hl || clip_head == NULL)
30816 clip_head = head;
30817 BUILD_GLYPH_STRINGS (i, start, h, t,
30818 overlap_hl, dummy_x, last_x);
30819 for (s = h; s; s = s->next)
30820 s->background_filled_p = true;
30821 compute_overhangs_and_x (t, head->x, true);
30822 prepend_glyph_string_lists (&head, &tail, h, t);
30823 }
30824
30825
30826
30827
30828
30829 i = right_overwritten (tail);
30830 if (i >= 0)
30831 {
30832 enum draw_glyphs_face overlap_hl;
30833
30834 if (check_mouse_face
30835 && mouse_beg_col < i && mouse_end_col > end)
30836 overlap_hl = DRAW_MOUSE_FACE;
30837 else
30838 overlap_hl = DRAW_NORMAL_TEXT;
30839
30840 if (hl != overlap_hl)
30841 clip_tail = tail;
30842 BUILD_GLYPH_STRINGS (end, i, h, t,
30843 overlap_hl, x, last_x);
30844
30845
30846 compute_overhangs_and_x (h, tail->x + tail->width, false);
30847 append_glyph_string_lists (&head, &tail, h, t);
30848 if (clip_tail == NULL)
30849 clip_tail = tail;
30850 }
30851
30852
30853
30854
30855
30856
30857 i = right_overwriting (tail);
30858 if (i >= 0)
30859 {
30860 enum draw_glyphs_face overlap_hl;
30861 if (check_mouse_face
30862 && mouse_beg_col < i && mouse_end_col > end)
30863 overlap_hl = DRAW_MOUSE_FACE;
30864 else
30865 overlap_hl = DRAW_NORMAL_TEXT;
30866
30867 if (hl == overlap_hl || clip_tail == NULL)
30868 clip_tail = tail;
30869 i++;
30870 BUILD_GLYPH_STRINGS (end, i, h, t,
30871 overlap_hl, x, last_x);
30872 for (s = h; s; s = s->next)
30873 s->background_filled_p = true;
30874 compute_overhangs_and_x (h, tail->x + tail->width, false);
30875 append_glyph_string_lists (&head, &tail, h, t);
30876 }
30877 tail = glyph_string_containing_background_width (tail);
30878 if (clip_tail)
30879 clip_tail = glyph_string_containing_background_width (clip_tail);
30880 if (clip_head || clip_tail)
30881 for (s = head; s; s = s->next)
30882 {
30883 s->clip_head = clip_head;
30884 s->clip_tail = clip_tail;
30885 }
30886 }
30887
30888
30889 for (s = head; s; s = s->next)
30890 FRAME_RIF (f)->draw_glyph_string (s);
30891
30892
30893
30894 if (area == TEXT_AREA
30895 && !row->full_width_p
30896
30897
30898
30899 && !overlaps)
30900 {
30901 int x0 = clip_head ? clip_head->x : (head ? head->x : x);
30902 int x1 = (clip_tail ? clip_tail->x + clip_tail->background_width
30903 : (tail ? tail->x + tail->background_width : x));
30904 x0 -= area_left;
30905 x1 -= area_left;
30906
30907 notice_overwritten_cursor (w, TEXT_AREA, x0, x1,
30908 row->y, MATRIX_ROW_BOTTOM_Y (row));
30909 }
30910
30911
30912
30913 if (row->full_width_p)
30914 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
30915 else
30916 x_reached -= area_left;
30917
30918 RELEASE_HDC (hdc, f);
30919
30920 SAFE_FREE ();
30921 return x_reached;
30922 }
30923
30924
30925
30926
30927
30928
30929
30930
30931 struct font *
30932 font_for_underline_metrics (struct glyph_string *s)
30933 {
30934 struct glyph *g0 = s->row->glyphs[s->area], *g;
30935
30936 for (g = s->first_glyph - 1; g >= g0; g--)
30937 {
30938 struct face *prev_face = FACE_FROM_ID (s->f, g->face_id);
30939 if (!(prev_face && prev_face->underline != FACE_NO_UNDERLINE))
30940 break;
30941 }
30942
30943
30944 if (g == s->first_glyph - 1)
30945 return s->font;
30946 else
30947 {
30948
30949
30950 return FACE_FROM_ID (s->f, g[1].face_id)->font;
30951 }
30952 }
30953
30954
30955
30956
30957 #define IT_EXPAND_MATRIX_WIDTH(it, area) \
30958 { \
30959 if (!it->f->fonts_changed \
30960 && (it->glyph_row->glyphs[area] \
30961 < it->glyph_row->glyphs[area + 1])) \
30962 { \
30963 it->w->ncols_scale_factor++; \
30964 it->f->fonts_changed = true; \
30965 } \
30966 }
30967
30968
30969
30970
30971 static void
30972 append_glyph (struct it *it)
30973 {
30974 struct glyph *glyph;
30975 enum glyph_row_area area = it->area;
30976
30977 eassert (it->glyph_row);
30978 eassert (it->char_to_display != '\n' && it->char_to_display != '\t');
30979
30980 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
30981 if (glyph < it->glyph_row->glyphs[area + 1])
30982 {
30983
30984
30985 if (it->glyph_row->reversed_p && area == TEXT_AREA)
30986 {
30987 struct glyph *g;
30988
30989
30990 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
30991 g[1] = *g;
30992 glyph = it->glyph_row->glyphs[area];
30993 }
30994 glyph->charpos = CHARPOS (it->position);
30995 glyph->object = it->object;
30996 if (it->pixel_width > 0)
30997 {
30998 eassert (it->pixel_width <= SHRT_MAX);
30999 glyph->pixel_width = it->pixel_width;
31000 glyph->padding_p = false;
31001 }
31002 else
31003 {
31004
31005
31006 glyph->pixel_width = 1;
31007 glyph->padding_p = true;
31008 }
31009 glyph->ascent = it->ascent;
31010 glyph->descent = it->descent;
31011 glyph->voffset = it->voffset;
31012 glyph->type = CHAR_GLYPH;
31013 glyph->avoid_cursor_p = it->avoid_cursor_p;
31014 glyph->multibyte_p = it->multibyte_p;
31015 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31016 {
31017
31018
31019 glyph->right_box_line_p = it->start_of_box_run_p;
31020 glyph->left_box_line_p = it->end_of_box_run_p;
31021 }
31022 else
31023 {
31024 glyph->left_box_line_p = it->start_of_box_run_p;
31025 glyph->right_box_line_p = it->end_of_box_run_p;
31026 }
31027 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
31028 || it->phys_descent > it->descent);
31029 glyph->glyph_not_available_p = it->glyph_not_available_p;
31030 glyph->face_id = it->face_id;
31031 glyph->u.ch = it->char_to_display;
31032 glyph->slice.img = null_glyph_slice;
31033 glyph->font_type = FONT_TYPE_UNKNOWN;
31034 if (it->bidi_p)
31035 {
31036 glyph->resolved_level = it->bidi_it.resolved_level;
31037 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31038 glyph->bidi_type = it->bidi_it.type;
31039 }
31040 else
31041 {
31042 glyph->resolved_level = 0;
31043 glyph->bidi_type = UNKNOWN_BT;
31044 }
31045 ++it->glyph_row->used[area];
31046 }
31047 else
31048 IT_EXPAND_MATRIX_WIDTH (it, area);
31049 }
31050
31051
31052
31053
31054 static void
31055 append_composite_glyph (struct it *it)
31056 {
31057 struct glyph *glyph;
31058 enum glyph_row_area area = it->area;
31059
31060 eassert (it->glyph_row);
31061
31062 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31063 if (glyph < it->glyph_row->glyphs[area + 1])
31064 {
31065
31066
31067 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
31068 {
31069 struct glyph *g;
31070
31071
31072 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31073 g[1] = *g;
31074 glyph = it->glyph_row->glyphs[it->area];
31075 }
31076 glyph->charpos = it->cmp_it.charpos;
31077 glyph->object = it->object;
31078 eassert (it->pixel_width <= SHRT_MAX);
31079 glyph->pixel_width = it->pixel_width;
31080 glyph->ascent = it->ascent;
31081 glyph->descent = it->descent;
31082 glyph->voffset = it->voffset;
31083 glyph->type = COMPOSITE_GLYPH;
31084 if (it->cmp_it.ch < 0)
31085 {
31086 glyph->u.cmp.automatic = false;
31087 glyph->u.cmp.id = it->cmp_it.id;
31088 glyph->slice.cmp.from = glyph->slice.cmp.to = 0;
31089 }
31090 else
31091 {
31092 glyph->u.cmp.automatic = true;
31093 glyph->u.cmp.id = it->cmp_it.id;
31094 glyph->slice.cmp.from = it->cmp_it.from;
31095 glyph->slice.cmp.to = it->cmp_it.to - 1;
31096 }
31097 glyph->avoid_cursor_p = it->avoid_cursor_p;
31098 glyph->multibyte_p = it->multibyte_p;
31099 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31100 {
31101
31102
31103 glyph->right_box_line_p = it->start_of_box_run_p;
31104 glyph->left_box_line_p = it->end_of_box_run_p;
31105 }
31106 else
31107 {
31108 glyph->left_box_line_p = it->start_of_box_run_p;
31109 glyph->right_box_line_p = it->end_of_box_run_p;
31110 }
31111 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
31112 || it->phys_descent > it->descent);
31113 glyph->padding_p = false;
31114 glyph->glyph_not_available_p = it->glyph_not_available_p;
31115 glyph->face_id = it->face_id;
31116 glyph->font_type = FONT_TYPE_UNKNOWN;
31117 if (it->bidi_p)
31118 {
31119 glyph->resolved_level = it->bidi_it.resolved_level;
31120 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31121 glyph->bidi_type = it->bidi_it.type;
31122 }
31123 ++it->glyph_row->used[area];
31124 }
31125 else
31126 IT_EXPAND_MATRIX_WIDTH (it, area);
31127 }
31128
31129
31130
31131
31132
31133 static void
31134 take_vertical_position_into_account (struct it *it)
31135 {
31136 if (it->voffset)
31137 {
31138 if (it->voffset < 0)
31139
31140
31141 it->ascent -= it->voffset;
31142 else
31143
31144
31145 it->descent += it->voffset;
31146 }
31147 }
31148
31149
31150
31151
31152
31153
31154 static void
31155 produce_image_glyph (struct it *it)
31156 {
31157 struct image *img;
31158 struct face *face;
31159 int glyph_ascent, crop;
31160 struct glyph_slice slice;
31161
31162 eassert (it->what == IT_IMAGE);
31163
31164 face = FACE_FROM_ID (it->f, it->face_id);
31165
31166 prepare_face_for_display (it->f, face);
31167
31168 if (it->image_id < 0)
31169 {
31170
31171 it->ascent = it->phys_ascent = 0;
31172 it->descent = it->phys_descent = 0;
31173 it->pixel_width = 0;
31174 it->nglyphs = 0;
31175 return;
31176 }
31177
31178 img = IMAGE_FROM_ID (it->f, it->image_id);
31179
31180 prepare_image_for_display (it->f, img);
31181
31182 slice.x = slice.y = 0;
31183 slice.width = img->width;
31184 slice.height = img->height;
31185
31186 if (FIXNUMP (it->slice.x))
31187 slice.x = XFIXNUM (it->slice.x);
31188 else if (FLOATP (it->slice.x))
31189 slice.x = XFLOAT_DATA (it->slice.x) * img->width;
31190
31191 if (FIXNUMP (it->slice.y))
31192 slice.y = XFIXNUM (it->slice.y);
31193 else if (FLOATP (it->slice.y))
31194 slice.y = XFLOAT_DATA (it->slice.y) * img->height;
31195
31196 if (FIXNUMP (it->slice.width))
31197 slice.width = XFIXNUM (it->slice.width);
31198 else if (FLOATP (it->slice.width))
31199 slice.width = XFLOAT_DATA (it->slice.width) * img->width;
31200
31201 if (FIXNUMP (it->slice.height))
31202 slice.height = XFIXNUM (it->slice.height);
31203 else if (FLOATP (it->slice.height))
31204 slice.height = XFLOAT_DATA (it->slice.height) * img->height;
31205
31206 if (slice.x >= img->width)
31207 slice.x = img->width;
31208 if (slice.y >= img->height)
31209 slice.y = img->height;
31210 if (slice.x + slice.width >= img->width)
31211 slice.width = img->width - slice.x;
31212 if (slice.y + slice.height > img->height)
31213 slice.height = img->height - slice.y;
31214
31215 if (slice.width == 0 || slice.height == 0)
31216 return;
31217
31218 it->ascent = it->phys_ascent = glyph_ascent = image_ascent (img, face, &slice);
31219
31220 it->descent = slice.height - glyph_ascent;
31221 if (slice.y == 0)
31222 it->descent += img->vmargin;
31223 if (slice.y + slice.height == img->height)
31224 it->descent += img->vmargin;
31225 it->phys_descent = it->descent;
31226
31227 it->pixel_width = slice.width;
31228 if (slice.x == 0)
31229 it->pixel_width += img->hmargin;
31230 if (slice.x + slice.width == img->width)
31231 it->pixel_width += img->hmargin;
31232
31233
31234
31235 if (it->descent < 0)
31236 it->descent = 0;
31237
31238 it->nglyphs = 1;
31239
31240 if (face->box != FACE_NO_BOX)
31241 {
31242
31243
31244 if (face->box_horizontal_line_width > 0)
31245 {
31246 if (slice.y == 0)
31247 it->ascent += face->box_horizontal_line_width;
31248 if (slice.y + slice.height == img->height)
31249 it->descent += face->box_horizontal_line_width;
31250 }
31251
31252 if (face->box_vertical_line_width > 0)
31253 {
31254 if (it->start_of_box_run_p && slice.x == 0)
31255 it->pixel_width += face->box_vertical_line_width;
31256 if (it->end_of_box_run_p && slice.x + slice.width == img->width)
31257 it->pixel_width += face->box_vertical_line_width;
31258 }
31259 }
31260
31261 take_vertical_position_into_account (it);
31262
31263
31264
31265 if ((crop = it->pixel_width - (it->last_visible_x - it->current_x), crop > 0)
31266 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
31267 {
31268 it->pixel_width -= crop;
31269 slice.width -= crop;
31270 }
31271
31272 if (it->glyph_row)
31273 {
31274 struct glyph *glyph;
31275 enum glyph_row_area area = it->area;
31276
31277 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31278 if (it->glyph_row->reversed_p)
31279 {
31280 struct glyph *g;
31281
31282
31283 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31284 g[1] = *g;
31285 glyph = it->glyph_row->glyphs[it->area];
31286 }
31287 if (glyph < it->glyph_row->glyphs[area + 1])
31288 {
31289 glyph->charpos = CHARPOS (it->position);
31290 glyph->object = it->object;
31291 glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
31292 glyph->ascent = glyph_ascent;
31293 glyph->descent = it->descent;
31294 glyph->voffset = it->voffset;
31295 glyph->type = IMAGE_GLYPH;
31296 glyph->avoid_cursor_p = it->avoid_cursor_p;
31297 glyph->multibyte_p = it->multibyte_p;
31298 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31299 {
31300
31301
31302 glyph->right_box_line_p = it->start_of_box_run_p;
31303 glyph->left_box_line_p = it->end_of_box_run_p;
31304 }
31305 else
31306 {
31307 glyph->left_box_line_p = it->start_of_box_run_p;
31308 glyph->right_box_line_p = it->end_of_box_run_p;
31309 }
31310 glyph->overlaps_vertically_p = false;
31311 glyph->padding_p = false;
31312 glyph->glyph_not_available_p = false;
31313 glyph->face_id = it->face_id;
31314 glyph->u.img_id = img->id;
31315 glyph->slice.img = slice;
31316 glyph->font_type = FONT_TYPE_UNKNOWN;
31317 if (it->bidi_p)
31318 {
31319 glyph->resolved_level = it->bidi_it.resolved_level;
31320 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31321 glyph->bidi_type = it->bidi_it.type;
31322 }
31323 ++it->glyph_row->used[area];
31324 }
31325 else
31326 IT_EXPAND_MATRIX_WIDTH (it, area);
31327 }
31328 }
31329
31330 static void
31331 produce_xwidget_glyph (struct it *it)
31332 {
31333 #ifdef HAVE_XWIDGETS
31334 struct xwidget *xw;
31335 int glyph_ascent, crop;
31336 eassert (it->what == IT_XWIDGET);
31337
31338 struct face *face = FACE_FROM_ID (it->f, it->face_id);
31339
31340 prepare_face_for_display (it->f, face);
31341
31342 xw = it->xwidget;
31343 it->ascent = it->phys_ascent = glyph_ascent = xw->height/2;
31344 it->descent = xw->height/2;
31345 it->phys_descent = it->descent;
31346 it->pixel_width = xw->width;
31347
31348
31349 if (it->descent < 0)
31350 it->descent = 0;
31351
31352 it->nglyphs = 1;
31353
31354 if (face->box != FACE_NO_BOX)
31355 {
31356 if (face->box_horizontal_line_width > 0)
31357 {
31358 it->ascent += face->box_horizontal_line_width;
31359 it->descent += face->box_horizontal_line_width;
31360 }
31361
31362 if (face->box_vertical_line_width > 0)
31363 {
31364 if (it->start_of_box_run_p)
31365 it->pixel_width += face->box_vertical_line_width;
31366 it->pixel_width += face->box_vertical_line_width;
31367 }
31368 }
31369
31370 take_vertical_position_into_account (it);
31371
31372
31373
31374 crop = it->pixel_width - (it->last_visible_x - it->current_x);
31375 if (crop > 0 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
31376 it->pixel_width -= crop;
31377
31378 if (it->glyph_row)
31379 {
31380 enum glyph_row_area area = it->area;
31381 struct glyph *glyph
31382 = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31383
31384 if (it->glyph_row->reversed_p)
31385 {
31386 struct glyph *g;
31387
31388
31389 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31390 g[1] = *g;
31391 glyph = it->glyph_row->glyphs[it->area];
31392 }
31393 if (glyph < it->glyph_row->glyphs[area + 1])
31394 {
31395 glyph->charpos = CHARPOS (it->position);
31396 glyph->object = it->object;
31397 glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
31398 glyph->ascent = glyph_ascent;
31399 glyph->descent = it->descent;
31400 glyph->voffset = it->voffset;
31401 glyph->type = XWIDGET_GLYPH;
31402 glyph->avoid_cursor_p = it->avoid_cursor_p;
31403 glyph->multibyte_p = it->multibyte_p;
31404 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31405 {
31406
31407
31408 glyph->right_box_line_p = it->start_of_box_run_p;
31409 glyph->left_box_line_p = it->end_of_box_run_p;
31410 }
31411 else
31412 {
31413 glyph->left_box_line_p = it->start_of_box_run_p;
31414 glyph->right_box_line_p = it->end_of_box_run_p;
31415 }
31416 glyph->overlaps_vertically_p = 0;
31417 glyph->padding_p = 0;
31418 glyph->glyph_not_available_p = 0;
31419 glyph->face_id = it->face_id;
31420 glyph->u.xwidget = it->xwidget->xwidget_id;
31421 glyph->font_type = FONT_TYPE_UNKNOWN;
31422 if (it->bidi_p)
31423 {
31424 glyph->resolved_level = it->bidi_it.resolved_level;
31425 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31426 glyph->bidi_type = it->bidi_it.type;
31427 }
31428 ++it->glyph_row->used[area];
31429 }
31430 else
31431 IT_EXPAND_MATRIX_WIDTH (it, area);
31432 }
31433 #endif
31434 }
31435
31436
31437
31438
31439
31440 static void
31441 append_stretch_glyph (struct it *it, Lisp_Object object,
31442 int width, int height, int ascent)
31443 {
31444 struct glyph *glyph;
31445 enum glyph_row_area area = it->area;
31446
31447 eassert (ascent >= 0 && ascent <= height);
31448
31449 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31450 if (glyph < it->glyph_row->glyphs[area + 1])
31451 {
31452
31453
31454 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31455 {
31456 struct glyph *g;
31457
31458
31459 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
31460 g[1] = *g;
31461 glyph = it->glyph_row->glyphs[area];
31462
31463
31464
31465
31466
31467
31468
31469
31470
31471
31472
31473
31474
31475
31476
31477 if (it->current_x < it->first_visible_x)
31478 width -= it->first_visible_x - it->current_x;
31479 eassert (width > 0);
31480 }
31481 glyph->charpos = CHARPOS (it->position);
31482 glyph->object = object;
31483
31484
31485 glyph->pixel_width = clip_to_bounds (-1, width, SHRT_MAX);
31486 glyph->ascent = ascent;
31487 glyph->descent = height - ascent;
31488 glyph->voffset = it->voffset;
31489 glyph->type = STRETCH_GLYPH;
31490 glyph->avoid_cursor_p = it->avoid_cursor_p;
31491 glyph->multibyte_p = it->multibyte_p;
31492 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31493 {
31494
31495
31496 glyph->right_box_line_p = it->start_of_box_run_p;
31497 glyph->left_box_line_p = it->end_of_box_run_p;
31498 }
31499 else
31500 {
31501 glyph->left_box_line_p = it->start_of_box_run_p;
31502 glyph->right_box_line_p = it->end_of_box_run_p;
31503 }
31504 glyph->overlaps_vertically_p = false;
31505 glyph->padding_p = false;
31506 glyph->glyph_not_available_p = false;
31507 glyph->face_id = it->face_id;
31508 glyph->u.stretch.ascent = ascent;
31509 glyph->u.stretch.height = height;
31510 glyph->slice.img = null_glyph_slice;
31511 glyph->font_type = FONT_TYPE_UNKNOWN;
31512 if (it->bidi_p)
31513 {
31514 glyph->resolved_level = it->bidi_it.resolved_level;
31515 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31516 glyph->bidi_type = it->bidi_it.type;
31517 }
31518 else
31519 {
31520 glyph->resolved_level = 0;
31521 glyph->bidi_type = UNKNOWN_BT;
31522 }
31523 ++it->glyph_row->used[area];
31524 }
31525 else
31526 IT_EXPAND_MATRIX_WIDTH (it, area);
31527 }
31528
31529 #endif
31530
31531
31532
31533
31534
31535
31536
31537
31538
31539
31540
31541
31542
31543
31544
31545
31546
31547
31548
31549
31550
31551
31552
31553
31554
31555
31556
31557
31558
31559
31560
31561
31562 void
31563 produce_stretch_glyph (struct it *it)
31564 {
31565
31566 Lisp_Object prop, plist;
31567 int width = 0, height = 0, align_to = -1;
31568 bool zero_width_ok_p = false;
31569 double tem;
31570 struct font *font = NULL;
31571
31572 #ifdef HAVE_WINDOW_SYSTEM
31573 int ascent = 0;
31574 bool zero_height_ok_p = false;
31575 struct face *face = NULL;
31576
31577 if (FRAME_WINDOW_P (it->f))
31578 {
31579 face = FACE_FROM_ID (it->f, it->face_id);
31580 font = face->font ? face->font : FRAME_FONT (it->f);
31581 prepare_face_for_display (it->f, face);
31582 }
31583 #endif
31584
31585
31586 eassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
31587 plist = XCDR (it->object);
31588
31589
31590 if ((prop = plist_get (plist, QCwidth), !NILP (prop))
31591 && calc_pixel_width_or_height (&tem, it, prop, font, true, NULL))
31592 {
31593
31594 zero_width_ok_p = true;
31595 width = (int)tem;
31596 }
31597 else if (prop = plist_get (plist, QCrelative_width), NUMVAL (prop) > 0)
31598 {
31599
31600
31601
31602 struct it it2;
31603 Lisp_Object object =
31604 it->sp > 0 ? it->stack[it->sp - 1].string : it->string;
31605 unsigned char *p = (STRINGP (object)
31606 ? SDATA (object) + IT_STRING_BYTEPOS (*it)
31607 : BYTE_POS_ADDR (IT_BYTEPOS (*it)));
31608 bool multibyte_p =
31609 STRINGP (object) ? STRING_MULTIBYTE (object) : it->multibyte_p;
31610
31611 it2 = *it;
31612 if (multibyte_p)
31613 {
31614 it2.c = it2.char_to_display = string_char_and_length (p, &it2.len);
31615 #ifdef HAVE_WINDOW_SYSTEM
31616 if (FRAME_WINDOW_P (it->f) && ! ASCII_CHAR_P (it2.c))
31617 it2.face_id = FACE_FOR_CHAR (it->f, face, it2.c,
31618 IT_CHARPOS (*it),
31619 STRINGP (object)? object : Qnil);
31620 #endif
31621 }
31622 else
31623 {
31624 it2.c = it2.char_to_display = *p, it2.len = 1;
31625 if (! ASCII_CHAR_P (it2.c))
31626 it2.char_to_display = BYTE8_TO_CHAR (it2.c);
31627 }
31628
31629 it2.glyph_row = NULL;
31630 it2.what = IT_CHARACTER;
31631 PRODUCE_GLYPHS (&it2);
31632 width = NUMVAL (prop) * it2.pixel_width;
31633 }
31634 else if ((prop = plist_get (plist, QCalign_to), !NILP (prop))
31635 && calc_pixel_width_or_height (&tem, it, prop, font, true,
31636 &align_to))
31637 {
31638 int x = it->current_x + it->continuation_lines_width;
31639 int x0 = x;
31640
31641 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
31642 {
31643 x -= it->lnum_pixel_width;
31644
31645 if (x + it->stretch_adjust >= it->first_visible_x)
31646 x += it->stretch_adjust;
31647 }
31648
31649 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
31650 align_to = (align_to < 0
31651 ? 0
31652 : align_to - window_box_left_offset (it->w, TEXT_AREA));
31653 else if (align_to < 0)
31654 align_to = window_box_left_offset (it->w, TEXT_AREA);
31655 width = max (0, (int)tem + align_to - x);
31656
31657 int next_x = x + width;
31658 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
31659 {
31660
31661
31662 if (x < it->first_visible_x)
31663 {
31664 next_x -= it->first_visible_x - x;
31665 it->stretch_adjust = it->first_visible_x - x;
31666 }
31667 else
31668 next_x -= it->stretch_adjust;
31669 }
31670 width = next_x - x0;
31671 zero_width_ok_p = true;
31672 }
31673 else
31674
31675 width = FRAME_COLUMN_WIDTH (it->f);
31676
31677 if (width <= 0 && (width < 0 || !zero_width_ok_p))
31678 width = 1;
31679
31680 #ifdef HAVE_WINDOW_SYSTEM
31681
31682 if (FRAME_WINDOW_P (it->f))
31683 {
31684 int default_height = normal_char_height (font, ' ');
31685
31686 if ((prop = plist_get (plist, QCheight), !NILP (prop))
31687 && calc_pixel_width_or_height (&tem, it, prop, font, false, NULL))
31688 {
31689 height = (int)tem;
31690 zero_height_ok_p = true;
31691 }
31692 else if (prop = plist_get (plist, QCrelative_height),
31693 NUMVAL (prop) > 0)
31694 height = default_height * NUMVAL (prop);
31695 else
31696 height = default_height;
31697
31698 if (height <= 0 && (height < 0 || !zero_height_ok_p))
31699 height = 1;
31700
31701
31702
31703
31704 if (prop = plist_get (plist, QCascent),
31705 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
31706 ascent = height * NUMVAL (prop) / 100.0;
31707 else if (!NILP (prop)
31708 && calc_pixel_width_or_height (&tem, it, prop, font, false, 0))
31709 ascent = min (max (0, (int)tem), height);
31710 else
31711 ascent = (height * FONT_BASE (font)) / FONT_HEIGHT (font);
31712 }
31713 else
31714 #endif
31715 height = 1;
31716
31717 if (width > 0
31718 && it->area == TEXT_AREA && it->line_wrap != TRUNCATE
31719 && it->current_x + width > it->last_visible_x)
31720 {
31721 width = it->last_visible_x - it->current_x;
31722 #ifdef HAVE_WINDOW_SYSTEM
31723
31724
31725 width -= FRAME_WINDOW_P (it->f);
31726 #endif
31727 }
31728
31729 if (width > 0 && height > 0 && it->glyph_row)
31730 {
31731 Lisp_Object o_object = it->object;
31732 Lisp_Object object =
31733 it->sp > 0 ? it->stack[it->sp - 1].string : it->string;
31734 int n = width;
31735
31736 if (!STRINGP (object))
31737 object = it->w->contents;
31738 #ifdef HAVE_WINDOW_SYSTEM
31739 if (FRAME_WINDOW_P (it->f))
31740 append_stretch_glyph (it, object, width, height, ascent);
31741 else
31742 #endif
31743 {
31744 it->object = object;
31745 it->char_to_display = ' ';
31746 it->pixel_width = it->len = 1;
31747 while (n--)
31748 tty_append_glyph (it);
31749 it->object = o_object;
31750 }
31751 }
31752
31753 it->pixel_width = width;
31754 #ifdef HAVE_WINDOW_SYSTEM
31755 if (FRAME_WINDOW_P (it->f))
31756 {
31757 it->ascent = it->phys_ascent = ascent;
31758 it->descent = it->phys_descent = height - it->ascent;
31759 it->nglyphs = width > 0 && height > 0;
31760 take_vertical_position_into_account (it);
31761 }
31762 else
31763 #endif
31764 it->nglyphs = width;
31765 }
31766
31767
31768
31769
31770
31771
31772
31773 static void
31774 produce_special_glyphs (struct it *it, enum display_element_type what)
31775 {
31776 struct it temp_it;
31777 Lisp_Object gc;
31778 GLYPH glyph;
31779
31780 temp_it = *it;
31781 temp_it.object = Qnil;
31782 memset (&temp_it.current, 0, sizeof temp_it.current);
31783
31784 if (what == IT_CONTINUATION)
31785 {
31786
31787 if (it->bidi_it.paragraph_dir == R2L)
31788 SET_GLYPH_FROM_CHAR (glyph, '/');
31789 else
31790 SET_GLYPH_FROM_CHAR (glyph, '\\');
31791 if (it->dp
31792 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc)))
31793 {
31794
31795 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
31796 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
31797 }
31798 }
31799 else if (what == IT_TRUNCATION)
31800 {
31801
31802 SET_GLYPH_FROM_CHAR (glyph, '$');
31803 if (it->dp
31804 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc)))
31805 {
31806
31807 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
31808 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
31809 }
31810 }
31811 else
31812 emacs_abort ();
31813
31814 #ifdef HAVE_WINDOW_SYSTEM
31815
31816
31817
31818
31819
31820 if (FRAME_WINDOW_P (temp_it.f)
31821
31822
31823
31824 && temp_it.glyph_row
31825
31826
31827
31828 && temp_it.glyph_row->used[TEXT_AREA] > 0
31829 && (temp_it.glyph_row->reversed_p
31830 ? WINDOW_LEFT_FRINGE_WIDTH (temp_it.w)
31831 : WINDOW_RIGHT_FRINGE_WIDTH (temp_it.w)) == 0)
31832 {
31833 int stretch_width = temp_it.last_visible_x - temp_it.current_x;
31834
31835 if (stretch_width > 0)
31836 {
31837 struct face *face = FACE_FROM_ID (temp_it.f, temp_it.face_id);
31838 struct font *font =
31839 face->font ? face->font : FRAME_FONT (temp_it.f);
31840 int stretch_ascent =
31841 (((temp_it.ascent + temp_it.descent)
31842 * FONT_BASE (font)) / FONT_HEIGHT (font));
31843
31844 append_stretch_glyph (&temp_it, Qnil, stretch_width,
31845 temp_it.ascent + temp_it.descent,
31846 stretch_ascent);
31847 }
31848 }
31849 #endif
31850
31851 temp_it.dp = NULL;
31852 temp_it.what = IT_CHARACTER;
31853 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
31854 temp_it.face_id = GLYPH_FACE (glyph);
31855 temp_it.len = CHAR_BYTES (temp_it.c);
31856
31857 PRODUCE_GLYPHS (&temp_it);
31858 it->pixel_width = temp_it.pixel_width;
31859 it->nglyphs = temp_it.nglyphs;
31860 }
31861
31862
31863
31864
31865
31866
31867
31868
31869
31870 static void
31871 pad_mode_line (struct it *it, bool mode_line_p)
31872 {
31873 struct it temp_it;
31874 GLYPH glyph;
31875
31876 eassert (!FRAME_WINDOW_P (it->f));
31877 temp_it = *it;
31878 temp_it.object = Qnil;
31879 memset (&temp_it.current, 0, sizeof temp_it.current);
31880
31881 SET_GLYPH (glyph, mode_line_p ? '-' : ' ', it->base_face_id);
31882
31883 temp_it.dp = NULL;
31884 temp_it.what = IT_CHARACTER;
31885 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
31886 temp_it.face_id = GLYPH_FACE (glyph);
31887 temp_it.len = CHAR_BYTES (temp_it.c);
31888
31889 PRODUCE_GLYPHS (&temp_it);
31890 it->pixel_width = temp_it.pixel_width;
31891 it->nglyphs = temp_it.nglyphs;
31892 }
31893
31894 #ifdef HAVE_WINDOW_SYSTEM
31895
31896
31897
31898
31899
31900
31901
31902
31903
31904 static Lisp_Object
31905 calc_line_height_property (struct it *it, Lisp_Object val, struct font *font,
31906 int boff, bool override)
31907 {
31908 Lisp_Object face_name = Qnil;
31909 int ascent, descent, height;
31910
31911 if (NILP (val) || INTEGERP (val) || (override && EQ (val, Qt)))
31912 return val;
31913
31914 if (CONSP (val))
31915 {
31916 face_name = XCAR (val);
31917 val = XCDR (val);
31918 if (!NUMBERP (val))
31919 val = make_fixnum (1);
31920 if (NILP (face_name))
31921 {
31922 height = it->ascent + it->descent;
31923 goto scale;
31924 }
31925 }
31926
31927 if (NILP (face_name))
31928 {
31929 font = FRAME_FONT (it->f);
31930 boff = FRAME_BASELINE_OFFSET (it->f);
31931 }
31932 else if (EQ (face_name, Qt))
31933 {
31934 override = false;
31935 }
31936 else
31937 {
31938 int face_id;
31939 struct face *face;
31940
31941 face_id = lookup_named_face (it->w, it->f, face_name, false);
31942 face = FACE_FROM_ID_OR_NULL (it->f, face_id);
31943 if (face == NULL || ((font = face->font) == NULL))
31944 return make_fixnum (-1);
31945 boff = font->baseline_offset;
31946 if (font->vertical_centering)
31947 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
31948 }
31949
31950 normal_char_ascent_descent (font, -1, &ascent, &descent);
31951
31952 if (override)
31953 {
31954 it->override_ascent = ascent;
31955 it->override_descent = descent;
31956 it->override_boff = boff;
31957 }
31958
31959 height = ascent + descent;
31960
31961 scale:
31962
31963 if (FLOATP (val))
31964 height = (int)(XFLOAT_DATA (val) * height);
31965 else if (INTEGERP (val))
31966 {
31967 intmax_t v;
31968 if (integer_to_intmax (val, &v))
31969 height *= v;
31970 }
31971
31972 return make_fixnum (height);
31973 }
31974
31975
31976
31977
31978
31979
31980
31981
31982
31983
31984
31985
31986
31987
31988 static void
31989 append_glyphless_glyph (struct it *it, int face_id, bool for_no_font, int len,
31990 short upper_xoff, short upper_yoff,
31991 short lower_xoff, short lower_yoff)
31992 {
31993 struct glyph *glyph;
31994 enum glyph_row_area area = it->area;
31995
31996 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31997 if (glyph < it->glyph_row->glyphs[area + 1])
31998 {
31999
32000
32001 if (it->glyph_row->reversed_p && area == TEXT_AREA)
32002 {
32003 struct glyph *g;
32004
32005
32006 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
32007 g[1] = *g;
32008 glyph = it->glyph_row->glyphs[area];
32009 }
32010 glyph->charpos = CHARPOS (it->position);
32011 glyph->object = it->object;
32012 eassert (it->pixel_width <= SHRT_MAX);
32013 glyph->pixel_width = it->pixel_width;
32014 glyph->ascent = it->ascent;
32015 glyph->descent = it->descent;
32016 glyph->voffset = it->voffset;
32017 glyph->type = GLYPHLESS_GLYPH;
32018 glyph->u.glyphless.method = it->glyphless_method;
32019 glyph->u.glyphless.for_no_font = for_no_font;
32020 glyph->u.glyphless.len = len;
32021 glyph->u.glyphless.ch = it->c;
32022 glyph->slice.glyphless.upper_xoff = upper_xoff;
32023 glyph->slice.glyphless.upper_yoff = upper_yoff;
32024 glyph->slice.glyphless.lower_xoff = lower_xoff;
32025 glyph->slice.glyphless.lower_yoff = lower_yoff;
32026 glyph->avoid_cursor_p = it->avoid_cursor_p;
32027 glyph->multibyte_p = it->multibyte_p;
32028 if (it->glyph_row->reversed_p && area == TEXT_AREA)
32029 {
32030
32031
32032 glyph->right_box_line_p = it->start_of_box_run_p;
32033 glyph->left_box_line_p = it->end_of_box_run_p;
32034 }
32035 else
32036 {
32037 glyph->left_box_line_p = it->start_of_box_run_p;
32038 glyph->right_box_line_p = it->end_of_box_run_p;
32039 }
32040 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
32041 || it->phys_descent > it->descent);
32042 glyph->padding_p = false;
32043 glyph->glyph_not_available_p = false;
32044 glyph->face_id = face_id;
32045 glyph->font_type = FONT_TYPE_UNKNOWN;
32046 if (it->bidi_p)
32047 {
32048 glyph->resolved_level = it->bidi_it.resolved_level;
32049 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
32050 glyph->bidi_type = it->bidi_it.type;
32051 }
32052 ++it->glyph_row->used[area];
32053 }
32054 else
32055 IT_EXPAND_MATRIX_WIDTH (it, area);
32056 }
32057
32058
32059
32060
32061
32062
32063
32064
32065
32066
32067
32068 static void
32069 produce_glyphless_glyph (struct it *it, bool for_no_font, Lisp_Object acronym)
32070 {
32071 int face_id;
32072 struct face *face;
32073 struct font *font;
32074 int base_width, base_height, width, height;
32075 short upper_xoff, upper_yoff, lower_xoff, lower_yoff;
32076 int len;
32077
32078
32079
32080 face = FACE_FROM_ID (it->f, it->face_id)->ascii_face;
32081 font = face->font ? face->font : FRAME_FONT (it->f);
32082 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
32083 it->ascent += font->baseline_offset;
32084 it->descent -= font->baseline_offset;
32085 base_height = it->ascent + it->descent;
32086 base_width = font->average_width;
32087
32088 face_id = merge_glyphless_glyph_face (it);
32089
32090 if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
32091 {
32092 it->pixel_width = THIN_SPACE_WIDTH;
32093 len = 0;
32094 upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
32095 }
32096 else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
32097 {
32098 width = CHARACTER_WIDTH (it->c);
32099 if (width == 0)
32100 width = 1;
32101 else if (width > 4)
32102 width = 4;
32103 it->pixel_width = base_width * width;
32104 len = 0;
32105 upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
32106 }
32107 else
32108 {
32109 char buf[7];
32110 const char *str;
32111 unsigned int code[6];
32112 int upper_len;
32113 int ascent, descent;
32114 struct font_metrics metrics_upper, metrics_lower;
32115
32116 face = FACE_FROM_ID (it->f, face_id);
32117 font = face->font ? face->font : FRAME_FONT (it->f);
32118 prepare_face_for_display (it->f, face);
32119
32120 if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
32121 {
32122 if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
32123 acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
32124 if (CONSP (acronym))
32125 acronym = XCAR (acronym);
32126 str = STRINGP (acronym) ? SSDATA (acronym) : "";
32127 }
32128 else
32129 {
32130 eassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
32131 sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c + 0u);
32132 str = buf;
32133 }
32134 for (len = 0; str[len] && ASCII_CHAR_P (str[len]) && len < 6; len++)
32135 code[len] = font->driver->encode_char (font, str[len]);
32136 upper_len = (len + 1) / 2;
32137 font->driver->text_extents (font, code, upper_len,
32138 &metrics_upper);
32139 font->driver->text_extents (font, code + upper_len, len - upper_len,
32140 &metrics_lower);
32141
32142
32143
32144
32145 width = max (metrics_upper.width, metrics_lower.width) + 4;
32146 upper_xoff = lower_xoff = 2;
32147 if (base_width >= width)
32148 {
32149
32150 it->pixel_width = base_width;
32151 lower_xoff = base_width - 2 - metrics_lower.width;
32152 }
32153 else
32154 {
32155
32156 it->pixel_width = width;
32157 if (metrics_upper.width >= metrics_lower.width)
32158 lower_xoff = (width - metrics_lower.width) / 2;
32159 else
32160 upper_xoff = (width - metrics_upper.width) / 2;
32161 }
32162
32163
32164
32165 height = (metrics_upper.ascent + metrics_upper.descent
32166 + metrics_lower.ascent + metrics_lower.descent) + 5;
32167
32168
32169
32170
32171
32172
32173
32174
32175 ascent = - (it->descent - (base_height + height + 1) / 2);
32176 descent = it->descent - (base_height - height) / 2;
32177 lower_yoff = descent - 2 - metrics_lower.descent;
32178 upper_yoff = (lower_yoff - metrics_lower.ascent - 1
32179 - metrics_upper.descent);
32180
32181 if (height > base_height)
32182 {
32183 it->ascent = ascent;
32184 it->descent = descent;
32185 }
32186 }
32187
32188 it->phys_ascent = it->ascent;
32189 it->phys_descent = it->descent;
32190 if (it->glyph_row)
32191 append_glyphless_glyph (it, face_id, for_no_font, len,
32192 upper_xoff, upper_yoff,
32193 lower_xoff, lower_yoff);
32194 it->nglyphs = 1;
32195 take_vertical_position_into_account (it);
32196 }
32197
32198
32199
32200
32201
32202 #define IT_APPLY_FACE_BOX(it, face) \
32203 do { \
32204 if (face->box != FACE_NO_BOX) \
32205 { \
32206 int thick = face->box_horizontal_line_width; \
32207 if (thick > 0) \
32208 { \
32209 it->ascent += thick; \
32210 it->descent += thick; \
32211 } \
32212 \
32213 thick = face->box_vertical_line_width; \
32214 if (thick > 0) \
32215 { \
32216 if (it->start_of_box_run_p) \
32217 it->pixel_width += thick; \
32218 if (it->end_of_box_run_p) \
32219 it->pixel_width += thick; \
32220 } \
32221 } \
32222 } while (false)
32223
32224
32225
32226
32227
32228
32229 void
32230 gui_produce_glyphs (struct it *it)
32231 {
32232 int extra_line_spacing = it->extra_line_spacing;
32233
32234 it->glyph_not_available_p = false;
32235
32236 if (it->what == IT_CHARACTER)
32237 {
32238 unsigned char2b;
32239 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32240 struct font *font = face->font;
32241 struct font_metrics *pcm = NULL;
32242 int boff;
32243
32244 if (font == NULL)
32245 {
32246
32247
32248
32249 Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
32250
32251 eassert (it->what == IT_GLYPHLESS);
32252 produce_glyphless_glyph (it, true,
32253 STRINGP (acronym) ? acronym : Qnil);
32254 goto done;
32255 }
32256
32257 boff = font->baseline_offset;
32258 if (font->vertical_centering)
32259 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
32260
32261 if (it->char_to_display != '\n' && it->char_to_display != '\t')
32262 {
32263 it->nglyphs = 1;
32264
32265 if (it->override_ascent >= 0)
32266 {
32267 it->ascent = it->override_ascent;
32268 it->descent = it->override_descent;
32269 boff = it->override_boff;
32270 }
32271 else
32272 {
32273 it->ascent = FONT_BASE (font) + boff;
32274 it->descent = FONT_DESCENT (font) - boff;
32275 }
32276
32277 if (get_char_glyph_code (it->char_to_display, font, &char2b))
32278 {
32279 pcm = get_per_char_metric (font, &char2b);
32280 if (pcm->width == 0
32281 && pcm->rbearing == 0 && pcm->lbearing == 0)
32282 pcm = NULL;
32283 }
32284
32285 if (pcm)
32286 {
32287 it->phys_ascent = pcm->ascent + boff;
32288 it->phys_descent = pcm->descent - boff;
32289 it->pixel_width = pcm->width;
32290
32291
32292 if (it->override_ascent < 0)
32293 {
32294 if (FONT_TOO_HIGH (font))
32295 {
32296 it->ascent = it->phys_ascent;
32297 it->descent = it->phys_descent;
32298
32299
32300 if (it->ascent < 0)
32301 it->ascent = 0;
32302 if (it->descent < 0)
32303 it->descent = 0;
32304 }
32305 }
32306 }
32307 else
32308 {
32309 it->glyph_not_available_p = true;
32310 it->phys_ascent = it->ascent;
32311 it->phys_descent = it->descent;
32312 it->pixel_width = font->space_width;
32313 }
32314
32315 if (it->constrain_row_ascent_descent_p)
32316 {
32317 if (it->descent > it->max_descent)
32318 {
32319 it->ascent += it->descent - it->max_descent;
32320 it->descent = it->max_descent;
32321 }
32322 if (it->ascent > it->max_ascent)
32323 {
32324 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
32325 it->ascent = it->max_ascent;
32326 }
32327 it->phys_ascent = min (it->phys_ascent, it->ascent);
32328 it->phys_descent = min (it->phys_descent, it->descent);
32329 extra_line_spacing = 0;
32330 }
32331
32332
32333
32334 bool stretched_p
32335 = it->char_to_display == ' ' && !NILP (it->space_width);
32336 if (stretched_p)
32337 it->pixel_width *= XFLOATINT (it->space_width);
32338
32339 IT_APPLY_FACE_BOX(it, face);
32340
32341
32342
32343 if (face->overline_p)
32344 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32345
32346 if (it->constrain_row_ascent_descent_p)
32347 {
32348 if (it->ascent > it->max_ascent)
32349 it->ascent = it->max_ascent;
32350 if (it->descent > it->max_descent)
32351 it->descent = it->max_descent;
32352 }
32353
32354 take_vertical_position_into_account (it);
32355
32356
32357 if (it->glyph_row)
32358 {
32359 if (stretched_p)
32360 {
32361
32362
32363 int ascent = (((it->ascent + it->descent) * FONT_BASE (font))
32364 / FONT_HEIGHT (font));
32365 append_stretch_glyph (it, it->object, it->pixel_width,
32366 it->ascent + it->descent, ascent);
32367 }
32368 else
32369 append_glyph (it);
32370
32371
32372
32373
32374 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
32375 it->glyph_row->contains_overlapping_glyphs_p = true;
32376 }
32377 if (! stretched_p && it->pixel_width == 0)
32378
32379
32380 it->pixel_width = 1;
32381 }
32382 else if (it->char_to_display == '\n')
32383 {
32384
32385
32386
32387
32388 Lisp_Object height;
32389 Lisp_Object total_height = Qnil;
32390
32391 it->override_ascent = -1;
32392 it->pixel_width = 0;
32393 it->nglyphs = 0;
32394
32395 height = get_it_property (it, Qline_height);
32396
32397 if (CONSP (height)
32398 && CONSP (XCDR (height))
32399 && NILP (XCDR (XCDR (height))))
32400 {
32401 total_height = XCAR (XCDR (height));
32402 height = XCAR (height);
32403 }
32404 height = calc_line_height_property (it, height, font, boff, true);
32405
32406 if (it->override_ascent >= 0)
32407 {
32408 it->ascent = it->override_ascent;
32409 it->descent = it->override_descent;
32410 boff = it->override_boff;
32411 }
32412 else
32413 {
32414 if (FONT_TOO_HIGH (font))
32415 {
32416 it->ascent = font->pixel_size + boff - 1;
32417 it->descent = -boff + 1;
32418 if (it->descent < 0)
32419 it->descent = 0;
32420 }
32421 else
32422 {
32423 it->ascent = FONT_BASE (font) + boff;
32424 it->descent = FONT_DESCENT (font) - boff;
32425 }
32426 }
32427
32428 if (EQ (height, Qt))
32429 {
32430 if (it->descent > it->max_descent)
32431 {
32432 it->ascent += it->descent - it->max_descent;
32433 it->descent = it->max_descent;
32434 }
32435 if (it->ascent > it->max_ascent)
32436 {
32437 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
32438 it->ascent = it->max_ascent;
32439 }
32440 it->phys_ascent = min (it->phys_ascent, it->ascent);
32441 it->phys_descent = min (it->phys_descent, it->descent);
32442 it->constrain_row_ascent_descent_p = true;
32443 extra_line_spacing = 0;
32444 }
32445 else
32446 {
32447 Lisp_Object spacing;
32448
32449 it->phys_ascent = it->ascent;
32450 it->phys_descent = it->descent;
32451
32452 if ((it->max_ascent > 0 || it->max_descent > 0)
32453 && face->box != FACE_NO_BOX
32454 && face->box_horizontal_line_width > 0)
32455 {
32456 it->ascent += face->box_horizontal_line_width;
32457 it->descent += face->box_horizontal_line_width;
32458 }
32459 if (!NILP (height)
32460 && XFIXNUM (height) > it->ascent + it->descent)
32461 it->ascent = XFIXNUM (height) - it->descent;
32462
32463 if (!NILP (total_height))
32464 spacing = calc_line_height_property (it, total_height, font,
32465 boff, false);
32466 else
32467 {
32468 spacing = get_it_property (it, Qline_spacing);
32469 spacing = calc_line_height_property (it, spacing, font,
32470 boff, false);
32471 }
32472 if (FIXNUMP (spacing))
32473 {
32474 extra_line_spacing = XFIXNUM (spacing);
32475 if (!NILP (total_height))
32476 extra_line_spacing -= (it->phys_ascent + it->phys_descent);
32477 }
32478 }
32479 }
32480 else
32481 {
32482 if (font->space_width > 0)
32483 {
32484 int tab_width = it->tab_width * font->space_width;
32485 int x = it->current_x + it->continuation_lines_width;
32486 int x0 = x;
32487
32488 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
32489 {
32490 x -= it->lnum_pixel_width;
32491
32492 if (x + it->stretch_adjust >= it->first_visible_x)
32493 x += it->stretch_adjust;
32494 }
32495
32496 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
32497
32498
32499
32500
32501 if (next_tab_x - x < font->space_width)
32502 next_tab_x += tab_width;
32503 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
32504 {
32505 next_tab_x += it->lnum_pixel_width;
32506
32507
32508 if (x < it->first_visible_x)
32509 {
32510 next_tab_x -= it->first_visible_x - x;
32511 it->stretch_adjust = it->first_visible_x - x;
32512 }
32513 else
32514 next_tab_x -= it->stretch_adjust;
32515 }
32516
32517 it->pixel_width = next_tab_x - x0;
32518 it->nglyphs = 1;
32519 if (FONT_TOO_HIGH (font))
32520 {
32521 if (get_char_glyph_code (' ', font, &char2b))
32522 {
32523 pcm = get_per_char_metric (font, &char2b);
32524 if (pcm->width == 0
32525 && pcm->rbearing == 0 && pcm->lbearing == 0)
32526 pcm = NULL;
32527 }
32528
32529 if (pcm)
32530 {
32531 it->ascent = pcm->ascent + boff;
32532 it->descent = pcm->descent - boff;
32533 }
32534 else
32535 {
32536 it->ascent = font->pixel_size + boff - 1;
32537 it->descent = -boff + 1;
32538 }
32539 if (it->ascent < 0)
32540 it->ascent = 0;
32541 if (it->descent < 0)
32542 it->descent = 0;
32543 }
32544 else
32545 {
32546 it->ascent = FONT_BASE (font) + boff;
32547 it->descent = FONT_DESCENT (font) - boff;
32548 }
32549 it->phys_ascent = it->ascent;
32550 it->phys_descent = it->descent;
32551
32552 if (it->glyph_row)
32553 {
32554 append_stretch_glyph (it, it->object, it->pixel_width,
32555 it->ascent + it->descent, it->ascent);
32556 }
32557 }
32558 else
32559 {
32560 it->pixel_width = 0;
32561 it->nglyphs = 1;
32562 }
32563 }
32564
32565 if (FONT_TOO_HIGH (font))
32566 {
32567 int font_ascent, font_descent;
32568
32569
32570
32571
32572
32573
32574
32575
32576 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
32577 it->max_ascent = max (it->max_ascent, font_ascent);
32578 it->max_descent = max (it->max_descent, font_descent);
32579 }
32580
32581 if (it->ascent < 0)
32582 it->ascent = 0;
32583 if (it->descent < 0)
32584 it->descent = 0;
32585 }
32586 else if (it->what == IT_COMPOSITION && it->cmp_it.ch < 0)
32587 {
32588
32589
32590
32591
32592
32593
32594
32595
32596 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32597 int boff;
32598 struct composition *cmp = composition_table[it->cmp_it.id];
32599 int glyph_len = cmp->glyph_len;
32600 struct font *font = face->font;
32601
32602 it->nglyphs = 1;
32603
32604
32605
32606
32607
32608
32609
32610
32611 if (! cmp->font || cmp->font != font)
32612 {
32613
32614
32615
32616
32617 int font_ascent, font_descent, font_height;
32618
32619 int leftmost, rightmost, lowest, highest;
32620 int lbearing, rbearing;
32621 int i, width, ascent, descent;
32622 int c;
32623 unsigned char2b;
32624 struct font_metrics *pcm;
32625 ptrdiff_t pos;
32626
32627 eassume (0 < glyph_len);
32628 do
32629 c = COMPOSITION_GLYPH (cmp, glyph_len - 1);
32630 while (c == '\t' && 0 < --glyph_len);
32631
32632 bool right_padded = glyph_len < cmp->glyph_len;
32633 for (i = 0; i < glyph_len; i++)
32634 {
32635 c = COMPOSITION_GLYPH (cmp, i);
32636 if (c != '\t')
32637 break;
32638 cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
32639 }
32640 bool left_padded = i > 0;
32641
32642 pos = (STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
32643 : IT_CHARPOS (*it));
32644
32645 bool font_not_found_p = font == NULL;
32646 if (font_not_found_p)
32647 {
32648 face = face->ascii_face;
32649 font = face->font;
32650 }
32651 boff = font->baseline_offset;
32652 if (font->vertical_centering)
32653 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
32654 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
32655 font_ascent += boff;
32656 font_descent -= boff;
32657 font_height = font_ascent + font_descent;
32658
32659 cmp->font = font;
32660
32661 pcm = NULL;
32662 if (! font_not_found_p)
32663 {
32664 get_char_face_and_encoding (it->f, c, it->face_id,
32665 &char2b, false);
32666 pcm = get_per_char_metric (font, &char2b);
32667 }
32668
32669
32670 if (pcm)
32671 {
32672 width = cmp->glyph_len > 0 ? pcm->width : 0;
32673 ascent = pcm->ascent;
32674 descent = pcm->descent;
32675 lbearing = pcm->lbearing;
32676 rbearing = pcm->rbearing;
32677 }
32678 else
32679 {
32680 width = cmp->glyph_len > 0 ? font->space_width : 0;
32681 ascent = FONT_BASE (font);
32682 descent = FONT_DESCENT (font);
32683 lbearing = 0;
32684 rbearing = width;
32685 }
32686
32687 rightmost = width;
32688 leftmost = 0;
32689 lowest = - descent + boff;
32690 highest = ascent + boff;
32691
32692 if (! font_not_found_p
32693 && font->default_ascent
32694 && CHAR_TABLE_P (Vuse_default_ascent)
32695 && !NILP (Faref (Vuse_default_ascent,
32696 make_fixnum (it->char_to_display))))
32697 highest = font->default_ascent + boff;
32698
32699
32700
32701
32702 cmp->offsets[i * 2] = 0;
32703 cmp->offsets[i * 2 + 1] = boff;
32704 cmp->lbearing = lbearing;
32705 cmp->rbearing = rbearing;
32706
32707
32708 for (i++; i < glyph_len; i++)
32709 {
32710 int left, right, btm, top;
32711 int ch = COMPOSITION_GLYPH (cmp, i);
32712 int face_id;
32713 struct face *this_face;
32714
32715 if (ch == '\t')
32716 ch = ' ';
32717 face_id = FACE_FOR_CHAR (it->f, face, ch, pos, it->string);
32718 this_face = FACE_FROM_ID (it->f, face_id);
32719 font = this_face->font;
32720
32721 if (font == NULL)
32722 pcm = NULL;
32723 else
32724 {
32725 get_char_face_and_encoding (it->f, ch, face_id,
32726 &char2b, false);
32727 pcm = get_per_char_metric (font, &char2b);
32728 }
32729 if (! pcm)
32730 cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
32731 else
32732 {
32733 width = pcm->width;
32734 ascent = pcm->ascent;
32735 descent = pcm->descent;
32736 lbearing = pcm->lbearing;
32737 rbearing = pcm->rbearing;
32738 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
32739 {
32740
32741
32742 left = (leftmost + rightmost - width) / 2;
32743 btm = - descent + boff;
32744 if (font->relative_compose
32745 && (! CHAR_TABLE_P (Vignore_relative_composition)
32746 || NILP (Faref (Vignore_relative_composition,
32747 make_fixnum (ch)))))
32748 {
32749
32750 if (- descent >= font->relative_compose)
32751
32752 btm = highest + 1;
32753 else if (ascent <= 0)
32754
32755 btm = lowest - 1 - ascent - descent;
32756 }
32757 }
32758 else
32759 {
32760
32761
32762
32763
32764
32765
32766
32767
32768
32769
32770
32771
32772
32773
32774
32775 int rule = COMPOSITION_RULE (cmp, i);
32776 int gref, nref, grefx, grefy, nrefx, nrefy, xoff, yoff;
32777
32778 COMPOSITION_DECODE_RULE (rule, gref, nref, xoff, yoff);
32779 grefx = gref % 3, nrefx = nref % 3;
32780 grefy = gref / 3, nrefy = nref / 3;
32781 if (xoff)
32782 xoff = font_height * (xoff - 128) / 256;
32783 if (yoff)
32784 yoff = font_height * (yoff - 128) / 256;
32785
32786 left = (leftmost
32787 + grefx * (rightmost - leftmost) / 2
32788 - nrefx * width / 2
32789 + xoff);
32790
32791 btm = ((grefy == 0 ? highest
32792 : grefy == 1 ? 0
32793 : grefy == 2 ? lowest
32794 : (highest + lowest) / 2)
32795 - (nrefy == 0 ? ascent + descent
32796 : nrefy == 1 ? descent - boff
32797 : nrefy == 2 ? 0
32798 : (ascent + descent) / 2)
32799 + yoff);
32800 }
32801
32802 cmp->offsets[i * 2] = left;
32803 cmp->offsets[i * 2 + 1] = btm + descent;
32804
32805
32806 if (width > 0)
32807 {
32808 right = left + width;
32809 if (left < leftmost)
32810 leftmost = left;
32811 if (right > rightmost)
32812 rightmost = right;
32813 }
32814 top = btm + descent + ascent;
32815 if (top > highest)
32816 highest = top;
32817 if (btm < lowest)
32818 lowest = btm;
32819
32820 if (cmp->lbearing > left + lbearing)
32821 cmp->lbearing = left + lbearing;
32822 if (cmp->rbearing < left + rbearing)
32823 cmp->rbearing = left + rbearing;
32824 }
32825 }
32826
32827
32828
32829
32830 if (leftmost < 0)
32831 {
32832 for (i = 0; i < cmp->glyph_len; i++)
32833 cmp->offsets[i * 2] -= leftmost;
32834 rightmost -= leftmost;
32835 cmp->lbearing -= leftmost;
32836 cmp->rbearing -= leftmost;
32837 }
32838
32839 if (left_padded && cmp->lbearing < 0)
32840 {
32841 for (i = 0; i < cmp->glyph_len; i++)
32842 cmp->offsets[i * 2] -= cmp->lbearing;
32843 rightmost -= cmp->lbearing;
32844 cmp->rbearing -= cmp->lbearing;
32845 cmp->lbearing = 0;
32846 }
32847 if (right_padded && rightmost < cmp->rbearing)
32848 {
32849 rightmost = cmp->rbearing;
32850 }
32851
32852 cmp->pixel_width = rightmost;
32853 cmp->ascent = highest;
32854 cmp->descent = - lowest;
32855 if (cmp->ascent < font_ascent)
32856 cmp->ascent = font_ascent;
32857 if (cmp->descent < font_descent)
32858 cmp->descent = font_descent;
32859 }
32860
32861 if (it->glyph_row
32862 && (cmp->lbearing < 0
32863 || cmp->rbearing > cmp->pixel_width))
32864 it->glyph_row->contains_overlapping_glyphs_p = true;
32865
32866 it->pixel_width = cmp->pixel_width;
32867 it->ascent = it->phys_ascent = cmp->ascent;
32868 it->descent = it->phys_descent = cmp->descent;
32869 IT_APPLY_FACE_BOX(it, face);
32870
32871
32872
32873 if (face->overline_p)
32874 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32875
32876 take_vertical_position_into_account (it);
32877 if (it->ascent < 0)
32878 it->ascent = 0;
32879 if (it->descent < 0)
32880 it->descent = 0;
32881
32882 if (it->glyph_row && cmp->glyph_len > 0)
32883 append_composite_glyph (it);
32884 }
32885 else if (it->what == IT_COMPOSITION)
32886 {
32887
32888 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32889 Lisp_Object gstring;
32890 struct font_metrics metrics;
32891
32892 it->nglyphs = 1;
32893
32894 gstring = composition_gstring_from_id (it->cmp_it.id);
32895 it->pixel_width
32896 = composition_gstring_width (gstring, it->cmp_it.from, it->cmp_it.to,
32897 &metrics);
32898 if (it->pixel_width == 0)
32899 {
32900 it->glyph_not_available_p = true;
32901 it->phys_ascent = it->ascent;
32902 it->phys_descent = it->descent;
32903 it->pixel_width = face->font->space_width;
32904 }
32905 else
32906 {
32907 if (it->glyph_row
32908 && (metrics.lbearing < 0 || metrics.rbearing > metrics.width))
32909 it->glyph_row->contains_overlapping_glyphs_p = true;
32910 it->ascent = it->phys_ascent = metrics.ascent;
32911 it->descent = it->phys_descent = metrics.descent;
32912 }
32913 IT_APPLY_FACE_BOX(it, face);
32914
32915
32916
32917 if (face->overline_p)
32918 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32919 take_vertical_position_into_account (it);
32920 if (it->ascent < 0)
32921 it->ascent = 0;
32922 if (it->descent < 0)
32923 it->descent = 0;
32924
32925 if (it->glyph_row)
32926 append_composite_glyph (it);
32927 }
32928 else if (it->what == IT_GLYPHLESS)
32929 produce_glyphless_glyph (it, false, Qnil);
32930 else if (it->what == IT_IMAGE)
32931 produce_image_glyph (it);
32932 else if (it->what == IT_STRETCH)
32933 produce_stretch_glyph (it);
32934 else if (it->what == IT_XWIDGET)
32935 produce_xwidget_glyph (it);
32936
32937 done:
32938
32939
32940 eassert (it->ascent >= 0 && it->descent >= 0);
32941 if (it->area == TEXT_AREA)
32942 it->current_x += it->pixel_width;
32943
32944 if (extra_line_spacing > 0)
32945 {
32946 it->descent += extra_line_spacing;
32947 if (extra_line_spacing > it->max_extra_line_spacing)
32948 it->max_extra_line_spacing = extra_line_spacing;
32949 }
32950
32951 it->max_ascent = max (it->max_ascent, it->ascent);
32952 it->max_descent = max (it->max_descent, it->descent);
32953 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
32954 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
32955 }
32956
32957
32958
32959
32960
32961
32962 void
32963 gui_write_glyphs (struct window *w, struct glyph_row *updated_row,
32964 struct glyph *start, enum glyph_row_area updated_area, int len)
32965 {
32966 int x, hpos, chpos = w->phys_cursor.hpos;
32967
32968 eassert (updated_row);
32969
32970
32971
32972 if (!updated_row->reversed_p && chpos < 0)
32973 chpos = 0;
32974 if (updated_row->reversed_p && chpos >= updated_row->used[TEXT_AREA])
32975 chpos = updated_row->used[TEXT_AREA] - 1;
32976
32977 block_input ();
32978
32979
32980
32981 hpos = start - updated_row->glyphs[updated_area];
32982 x = draw_glyphs (w, w->output_cursor.x,
32983 updated_row, updated_area,
32984 hpos, hpos + len,
32985 DRAW_NORMAL_TEXT, 0);
32986
32987
32988 if (updated_area == TEXT_AREA
32989 && w->phys_cursor_on_p
32990 && w->phys_cursor.vpos == w->output_cursor.vpos
32991 && chpos >= hpos
32992 && chpos < hpos + len)
32993 w->phys_cursor_on_p = false;
32994
32995 unblock_input ();
32996
32997
32998 w->output_cursor.hpos += len;
32999 w->output_cursor.x = x;
33000 }
33001
33002
33003
33004
33005
33006 void
33007 gui_insert_glyphs (struct window *w, struct glyph_row *updated_row,
33008 struct glyph *start, enum glyph_row_area updated_area, int len)
33009 {
33010 struct frame *f;
33011 int line_height, shift_by_width, shifted_region_width;
33012 struct glyph_row *row;
33013 struct glyph *glyph;
33014 int frame_x, frame_y;
33015 ptrdiff_t hpos;
33016
33017 eassert (updated_row);
33018 block_input ();
33019 f = XFRAME (WINDOW_FRAME (w));
33020
33021
33022 row = updated_row;
33023 line_height = row->height;
33024
33025
33026 shift_by_width = 0;
33027 for (glyph = start; glyph < start + len; ++glyph)
33028 shift_by_width += glyph->pixel_width;
33029
33030
33031 shifted_region_width = (window_box_width (w, updated_area)
33032 - w->output_cursor.x
33033 - shift_by_width);
33034
33035
33036 frame_x = window_box_left (w, updated_area) + w->output_cursor.x;
33037 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, w->output_cursor.y);
33038
33039 FRAME_RIF (f)->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width,
33040 line_height, shift_by_width);
33041
33042
33043 hpos = start - row->glyphs[updated_area];
33044 draw_glyphs (w, w->output_cursor.x, row, updated_area,
33045 hpos, hpos + len,
33046 DRAW_NORMAL_TEXT, 0);
33047
33048
33049 w->output_cursor.hpos += len;
33050 w->output_cursor.x += shift_by_width;
33051 unblock_input ();
33052 }
33053
33054
33055
33056
33057
33058
33059
33060
33061
33062
33063 void
33064 gui_clear_end_of_line (struct window *w, struct glyph_row *updated_row,
33065 enum glyph_row_area updated_area, int to_x)
33066 {
33067 struct frame *f;
33068 int max_x, min_y, max_y;
33069 int from_x, from_y, to_y;
33070 struct face *face;
33071
33072 eassert (updated_row);
33073 f = XFRAME (w->frame);
33074 face = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID);
33075
33076 if (updated_row->full_width_p)
33077 max_x = (WINDOW_PIXEL_WIDTH (w)
33078 - (updated_row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
33079 else
33080 max_x = window_box_width (w, updated_area);
33081 max_y = window_text_bottom_y (w);
33082
33083
33084
33085 if (to_x == 0)
33086 return;
33087 else if (to_x < 0)
33088 to_x = max_x;
33089 else
33090 to_x = min (to_x, max_x);
33091
33092 to_y = min (max_y, w->output_cursor.y + updated_row->height);
33093
33094
33095 if (!updated_row->full_width_p)
33096 notice_overwritten_cursor (w, updated_area,
33097 w->output_cursor.x, -1,
33098 updated_row->y,
33099 MATRIX_ROW_BOTTOM_Y (updated_row));
33100
33101 from_x = w->output_cursor.x;
33102
33103
33104 if (updated_row->full_width_p)
33105 {
33106 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
33107 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
33108 }
33109 else
33110 {
33111 int area_left = window_box_left (w, updated_area);
33112 from_x += area_left;
33113 to_x += area_left;
33114 }
33115
33116 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
33117 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, w->output_cursor.y));
33118 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
33119
33120
33121 if (to_x > from_x && to_y > from_y)
33122 {
33123 block_input ();
33124 FRAME_RIF (f)->clear_frame_area (f, from_x, from_y,
33125 to_x - from_x, to_y - from_y);
33126
33127 if (face && !updated_row->stipple_p)
33128 updated_row->stipple_p = face->stipple;
33129 unblock_input ();
33130 }
33131 }
33132
33133 #endif
33134
33135
33136
33137
33138
33139
33140
33141
33142
33143
33144
33145 static enum text_cursor_kinds
33146 get_specified_cursor_type (Lisp_Object arg, int *width)
33147 {
33148 enum text_cursor_kinds type;
33149
33150 if (NILP (arg))
33151 return NO_CURSOR;
33152
33153 if (EQ (arg, Qbox))
33154 return FILLED_BOX_CURSOR;
33155
33156 if (EQ (arg, Qhollow))
33157 return HOLLOW_BOX_CURSOR;
33158
33159 if (EQ (arg, Qbar))
33160 {
33161 *width = 2;
33162 return BAR_CURSOR;
33163 }
33164
33165 if (EQ (arg, Qhbar))
33166 {
33167 *width = 2;
33168 return HBAR_CURSOR;
33169 }
33170
33171 if (CONSP (arg)
33172 && RANGED_FIXNUMP (0, XCDR (arg), INT_MAX))
33173 {
33174 *width = XFIXNUM (XCDR (arg));
33175
33176 if (EQ (XCAR (arg), Qbox))
33177 return FILLED_BOX_CURSOR;
33178 else if (EQ (XCAR (arg), Qbar))
33179 return BAR_CURSOR;
33180 else if (EQ (XCAR (arg), Qhbar))
33181 return HBAR_CURSOR;
33182 }
33183
33184
33185
33186
33187 type = HOLLOW_BOX_CURSOR;
33188
33189 return type;
33190 }
33191
33192
33193 void
33194 set_frame_cursor_types (struct frame *f, Lisp_Object arg)
33195 {
33196 int width = 1;
33197 Lisp_Object tem;
33198
33199 FRAME_DESIRED_CURSOR (f) = get_specified_cursor_type (arg, &width);
33200 FRAME_CURSOR_WIDTH (f) = width;
33201
33202
33203
33204 tem = Fassoc (arg, Vblink_cursor_alist, Qnil);
33205 if (!NILP (tem))
33206 {
33207 FRAME_BLINK_OFF_CURSOR (f)
33208 = get_specified_cursor_type (XCDR (tem), &width);
33209 FRAME_BLINK_OFF_CURSOR_WIDTH (f) = width;
33210 }
33211 else
33212 FRAME_BLINK_OFF_CURSOR (f) = DEFAULT_CURSOR;
33213
33214
33215 f->cursor_type_changed = true;
33216 }
33217
33218
33219 #ifdef HAVE_WINDOW_SYSTEM
33220
33221
33222
33223
33224
33225
33226
33227
33228
33229
33230
33231
33232 static enum text_cursor_kinds
33233 get_window_cursor_type (struct window *w, struct glyph *glyph, int *width,
33234 bool *active_cursor)
33235 {
33236 struct frame *f = XFRAME (w->frame);
33237 struct buffer *b = XBUFFER (w->contents);
33238 int cursor_type = DEFAULT_CURSOR;
33239 Lisp_Object alt_cursor;
33240 bool non_selected = false;
33241
33242 *active_cursor = true;
33243
33244
33245 if (cursor_in_echo_area
33246 && FRAME_HAS_MINIBUF_P (f)
33247 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
33248 {
33249 if (w == XWINDOW (echo_area_window))
33250 {
33251 if (EQ (BVAR (b, cursor_type), Qt) || NILP (BVAR (b, cursor_type)))
33252 {
33253 *width = FRAME_CURSOR_WIDTH (f);
33254 return FRAME_DESIRED_CURSOR (f);
33255 }
33256 else
33257 return get_specified_cursor_type (BVAR (b, cursor_type), width);
33258 }
33259
33260 *active_cursor = false;
33261 non_selected = true;
33262 }
33263
33264
33265 else if (w != XWINDOW (f->selected_window)
33266 || f != FRAME_DISPLAY_INFO (f)->highlight_frame)
33267 {
33268 *active_cursor = false;
33269
33270 if (MINI_WINDOW_P (w) &&
33271 (minibuf_level == 0
33272 || is_minibuffer (0, w->contents)))
33273 return NO_CURSOR;
33274
33275 non_selected = true;
33276 }
33277
33278
33279 if (NILP (BVAR (b, cursor_type)))
33280 return NO_CURSOR;
33281
33282
33283 if (EQ (BVAR (b, cursor_type), Qt))
33284 {
33285 cursor_type = FRAME_DESIRED_CURSOR (f);
33286 *width = FRAME_CURSOR_WIDTH (f);
33287 }
33288 else
33289 cursor_type = get_specified_cursor_type (BVAR (b, cursor_type), width);
33290
33291
33292
33293 if (non_selected)
33294 {
33295 alt_cursor = BVAR (b, cursor_in_non_selected_windows);
33296 if (!EQ (Qt, alt_cursor))
33297 return get_specified_cursor_type (alt_cursor, width);
33298
33299 if (cursor_type == FILLED_BOX_CURSOR)
33300 cursor_type = HOLLOW_BOX_CURSOR;
33301 else if (cursor_type == BAR_CURSOR && *width > 1)
33302 --*width;
33303 return cursor_type;
33304 }
33305
33306
33307 if (!w->cursor_off_p)
33308 {
33309 if (glyph != NULL && glyph->type == XWIDGET_GLYPH)
33310 return NO_CURSOR;
33311 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
33312 {
33313 if (cursor_type == FILLED_BOX_CURSOR)
33314 {
33315
33316
33317
33318
33319 struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
33320 if (img != NULL && IMAGEP (img->spec))
33321 {
33322
33323
33324
33325
33326
33327
33328 if (!img->mask
33329 || (CONSP (BVAR (b, cursor_type))
33330 && img->width > max (*width, WINDOW_FRAME_COLUMN_WIDTH (w))
33331 && img->height > max (*width, WINDOW_FRAME_LINE_HEIGHT (w))))
33332 cursor_type = HOLLOW_BOX_CURSOR;
33333 }
33334 }
33335 else if (cursor_type != NO_CURSOR)
33336 {
33337
33338
33339
33340 cursor_type = HOLLOW_BOX_CURSOR;
33341 }
33342 }
33343 return cursor_type;
33344 }
33345
33346
33347
33348
33349 if ((alt_cursor = Fassoc (BVAR (b, cursor_type), Vblink_cursor_alist, Qnil), !NILP (alt_cursor)))
33350 return get_specified_cursor_type (XCDR (alt_cursor), width);
33351
33352
33353 if (FRAME_BLINK_OFF_CURSOR (f) != DEFAULT_CURSOR)
33354 {
33355 *width = FRAME_BLINK_OFF_CURSOR_WIDTH (f);
33356 return FRAME_BLINK_OFF_CURSOR (f);
33357 }
33358
33359 #if false
33360
33361
33362
33363
33364
33365
33366
33367
33368
33369
33370 if (cursor_type == FILLED_BOX_CURSOR)
33371 return HOLLOW_BOX_CURSOR;
33372
33373 if ((cursor_type == BAR_CURSOR || cursor_type == HBAR_CURSOR) && *width > 1)
33374 {
33375 *width = 1;
33376 return cursor_type;
33377 }
33378 #endif
33379
33380 return NO_CURSOR;
33381 }
33382
33383
33384
33385
33386
33387
33388
33389
33390
33391 static void
33392 notice_overwritten_cursor (struct window *w, enum glyph_row_area area,
33393 int x0, int x1, int y0, int y1)
33394 {
33395 int cx0, cx1, cy0, cy1;
33396 struct glyph_row *row;
33397
33398 if (!w->phys_cursor_on_p)
33399 return;
33400 if (area != TEXT_AREA)
33401 return;
33402
33403 if (w->phys_cursor.vpos < 0
33404 || w->phys_cursor.vpos >= w->current_matrix->nrows
33405 || (row = w->current_matrix->rows + w->phys_cursor.vpos,
33406 !(row->enabled_p && MATRIX_ROW_DISPLAYS_TEXT_P (row))))
33407 return;
33408
33409 if (row->cursor_in_fringe_p)
33410 {
33411 row->cursor_in_fringe_p = false;
33412 draw_fringe_bitmap (w, row, row->reversed_p);
33413 w->phys_cursor_on_p = false;
33414 return;
33415 }
33416
33417 cx0 = w->phys_cursor.x;
33418 cx1 = cx0 + w->phys_cursor_width;
33419 if (x0 > cx0 || (x1 >= 0 && x1 < cx1))
33420 return;
33421
33422
33423
33424
33425
33426
33427
33428
33429
33430
33431
33432
33433
33434
33435
33436
33437
33438 cy0 = w->phys_cursor.y;
33439 cy1 = cy0 + w->phys_cursor_height;
33440 if ((y0 < cy0 || y0 >= cy1) && (y1 <= cy0 || y1 >= cy1))
33441 return;
33442
33443 w->phys_cursor_on_p = false;
33444 }
33445
33446 #endif
33447
33448
33449
33450
33451
33452
33453 #ifdef HAVE_WINDOW_SYSTEM
33454
33455
33456
33457
33458
33459 void
33460 gui_fix_overlapping_area (struct window *w, struct glyph_row *row,
33461 enum glyph_row_area area, int overlaps)
33462 {
33463 int i, x;
33464
33465 block_input ();
33466
33467 x = 0;
33468 for (i = 0; i < row->used[area];)
33469 {
33470 if (row->glyphs[area][i].overlaps_vertically_p)
33471 {
33472 int start = i, start_x = x;
33473
33474 do
33475 {
33476 x += row->glyphs[area][i].pixel_width;
33477 ++i;
33478 }
33479 while (i < row->used[area]
33480 && row->glyphs[area][i].overlaps_vertically_p);
33481
33482 draw_glyphs (w, start_x, row, area,
33483 start, i,
33484 DRAW_NORMAL_TEXT, overlaps);
33485 }
33486 else
33487 {
33488 x += row->glyphs[area][i].pixel_width;
33489 ++i;
33490 }
33491 }
33492
33493 unblock_input ();
33494 }
33495
33496
33497
33498
33499
33500
33501 void
33502 draw_phys_cursor_glyph (struct window *w, struct glyph_row *row,
33503 enum draw_glyphs_face hl)
33504 {
33505
33506
33507
33508 if ((row->reversed_p
33509 ? (w->phys_cursor.hpos >= 0)
33510 : (w->phys_cursor.hpos < row->used[TEXT_AREA])))
33511 {
33512 bool on_p = w->phys_cursor_on_p;
33513 int x1;
33514 int hpos = w->phys_cursor.hpos;
33515
33516
33517
33518
33519 if (!row->reversed_p && hpos < 0)
33520 hpos = 0;
33521 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33522 hpos = row->used[TEXT_AREA] - 1;
33523
33524 x1 = draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA, hpos, hpos + 1,
33525 hl, 0);
33526 w->phys_cursor_on_p = on_p;
33527
33528 if (hl == DRAW_CURSOR)
33529 w->phys_cursor_width = x1 - w->phys_cursor.x;
33530
33531
33532
33533 else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
33534 {
33535 w->phys_cursor_width = x1 - w->phys_cursor.x;
33536
33537 if (row > w->current_matrix->rows
33538 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
33539 gui_fix_overlapping_area (w, row - 1, TEXT_AREA,
33540 OVERLAPS_ERASED_CURSOR);
33541
33542 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
33543 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
33544 gui_fix_overlapping_area (w, row + 1, TEXT_AREA,
33545 OVERLAPS_ERASED_CURSOR);
33546 }
33547 }
33548 }
33549
33550
33551
33552
33553 void
33554 erase_phys_cursor (struct window *w)
33555 {
33556 struct frame *f = XFRAME (w->frame);
33557 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
33558 int hpos = w->phys_cursor.hpos;
33559 int vpos = w->phys_cursor.vpos;
33560 bool mouse_face_here_p = false;
33561 struct glyph_matrix *active_glyphs = w->current_matrix;
33562 struct glyph_row *cursor_row;
33563 struct glyph *cursor_glyph;
33564 enum draw_glyphs_face hl;
33565
33566
33567
33568 if (w->phys_cursor_type == NO_CURSOR)
33569 goto mark_cursor_off;
33570
33571
33572
33573 if (vpos >= active_glyphs->nrows)
33574 goto mark_cursor_off;
33575
33576
33577
33578 cursor_row = MATRIX_ROW (active_glyphs, vpos);
33579 if (!cursor_row->enabled_p)
33580 goto mark_cursor_off;
33581
33582
33583
33584 cursor_row->visible_height = min (cursor_row->visible_height,
33585 window_text_bottom_y (w) - cursor_row->y);
33586
33587
33588
33589
33590 if (cursor_row->visible_height <= 0)
33591 goto mark_cursor_off;
33592
33593
33594 if (cursor_row->cursor_in_fringe_p)
33595 {
33596 cursor_row->cursor_in_fringe_p = false;
33597 draw_fringe_bitmap (w, cursor_row, cursor_row->reversed_p);
33598 goto mark_cursor_off;
33599 }
33600
33601
33602
33603
33604
33605
33606 if ((cursor_row->reversed_p
33607 ? (w->phys_cursor.hpos < 0)
33608 : (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])))
33609 goto mark_cursor_off;
33610
33611
33612
33613
33614 if (!cursor_row->reversed_p && hpos < 0)
33615 hpos = 0;
33616 if (cursor_row->reversed_p && hpos >= cursor_row->used[TEXT_AREA])
33617 hpos = cursor_row->used[TEXT_AREA] - 1;
33618
33619
33620
33621 if (! NILP (hlinfo->mouse_face_window)
33622 && coords_in_mouse_face_p (w, hpos, vpos)
33623
33624
33625
33626 && cursor_row->used[TEXT_AREA] > hpos && hpos >= 0)
33627 mouse_face_here_p = true;
33628
33629 #ifdef HAVE_WINDOW_SYSTEM
33630
33631
33632
33633
33634 if (FRAME_WINDOW_P (WINDOW_XFRAME (w)) && mouse_face_here_p)
33635 {
33636 w->phys_cursor_on_p = false;
33637 w->phys_cursor_type = NO_CURSOR;
33638 show_mouse_face (MOUSE_HL_INFO (WINDOW_XFRAME (w)), DRAW_MOUSE_FACE);
33639 return;
33640 }
33641 #endif
33642
33643
33644 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
33645 {
33646 int x, y;
33647 int tab_line_height = WINDOW_TAB_LINE_HEIGHT (w);
33648 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
33649 int width;
33650
33651 cursor_glyph = get_phys_cursor_glyph (w);
33652 if (cursor_glyph == NULL)
33653 goto mark_cursor_off;
33654
33655 width = cursor_glyph->pixel_width;
33656 x = w->phys_cursor.x;
33657 if (x < 0)
33658 {
33659 width += x;
33660 x = 0;
33661 }
33662 width = min (width, window_box_width (w, TEXT_AREA) - x);
33663 y = WINDOW_TO_FRAME_PIXEL_Y (w, max (tab_line_height, max (header_line_height, cursor_row->y)));
33664 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
33665
33666 if (width > 0)
33667 FRAME_RIF (f)->clear_frame_area (f, x, y, width, cursor_row->visible_height);
33668 }
33669
33670
33671 if (mouse_face_here_p)
33672 hl = DRAW_MOUSE_FACE;
33673 else
33674 hl = DRAW_NORMAL_TEXT;
33675 draw_phys_cursor_glyph (w, cursor_row, hl);
33676
33677 mark_cursor_off:
33678 w->phys_cursor_on_p = false;
33679 w->phys_cursor_type = NO_CURSOR;
33680 }
33681
33682
33683
33684
33685
33686
33687 void
33688 display_and_set_cursor (struct window *w, bool on,
33689 int hpos, int vpos, int x, int y)
33690 {
33691 struct frame *f = XFRAME (w->frame);
33692 int new_cursor_type;
33693 int new_cursor_width UNINIT;
33694 bool active_cursor;
33695 struct glyph_row *glyph_row;
33696 struct glyph *glyph;
33697
33698
33699
33700
33701
33702 if (! FRAME_REDISPLAY_P (f)
33703 || vpos >= w->current_matrix->nrows
33704 || hpos >= w->current_matrix->matrix_w)
33705 return;
33706
33707
33708 if (!on && !w->phys_cursor_on_p)
33709 return;
33710
33711 glyph_row = MATRIX_ROW (w->current_matrix, vpos);
33712
33713
33714 if (!glyph_row->enabled_p)
33715 {
33716 w->phys_cursor_on_p = false;
33717 return;
33718 }
33719
33720
33721
33722
33723
33724
33725
33726
33727
33728 if (FRAME_GARBAGED_P (f))
33729 {
33730 if (on)
33731 {
33732 w->phys_cursor.x = x;
33733 w->phys_cursor.y = glyph_row->y;
33734 w->phys_cursor.hpos = hpos;
33735 w->phys_cursor.vpos = vpos;
33736 }
33737 return;
33738 }
33739
33740 glyph = NULL;
33741 if (0 <= hpos && hpos < glyph_row->used[TEXT_AREA])
33742 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
33743
33744 eassert (input_blocked_p ());
33745
33746
33747 new_cursor_type = get_window_cursor_type (w, glyph,
33748 &new_cursor_width, &active_cursor);
33749
33750
33751
33752
33753 if (w->phys_cursor_on_p
33754 && (!on
33755 || w->phys_cursor.x != x
33756 || w->phys_cursor.y != y
33757
33758
33759
33760 || hpos < 0
33761 || new_cursor_type != w->phys_cursor_type
33762 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
33763 && new_cursor_width != w->phys_cursor_width)))
33764 erase_phys_cursor (w);
33765
33766
33767
33768
33769
33770
33771 if (on)
33772 {
33773 w->phys_cursor_ascent = glyph_row->ascent;
33774 w->phys_cursor_height = glyph_row->height;
33775
33776
33777
33778 w->phys_cursor.x = x;
33779 w->phys_cursor.y = glyph_row->y;
33780 w->phys_cursor.hpos = hpos;
33781 w->phys_cursor.vpos = vpos;
33782 }
33783
33784 FRAME_RIF (f)->draw_window_cursor (w, glyph_row, x, y,
33785 new_cursor_type, new_cursor_width,
33786 on, active_cursor);
33787 }
33788
33789
33790
33791
33792
33793 static void
33794 update_window_cursor (struct window *w, bool on)
33795 {
33796
33797
33798 if (w->current_matrix)
33799 {
33800 int hpos = w->phys_cursor.hpos;
33801 int vpos = w->phys_cursor.vpos;
33802 struct glyph_row *row;
33803
33804 if (vpos >= w->current_matrix->nrows
33805 || hpos >= w->current_matrix->matrix_w)
33806 return;
33807
33808 row = MATRIX_ROW (w->current_matrix, vpos);
33809
33810
33811
33812
33813 if (!row->reversed_p && hpos < 0)
33814 hpos = 0;
33815 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33816 hpos = row->used[TEXT_AREA] - 1;
33817
33818 block_input ();
33819 display_and_set_cursor (w, on, hpos, vpos,
33820 w->phys_cursor.x, w->phys_cursor.y);
33821 unblock_input ();
33822 }
33823 }
33824
33825
33826
33827
33828
33829 static void
33830 update_cursor_in_window_tree (struct window *w, bool on_p)
33831 {
33832 while (w)
33833 {
33834 if (WINDOWP (w->contents))
33835 update_cursor_in_window_tree (XWINDOW (w->contents), on_p);
33836 else
33837 update_window_cursor (w, on_p);
33838
33839 w = NILP (w->next) ? 0 : XWINDOW (w->next);
33840 }
33841 }
33842
33843
33844
33845
33846
33847
33848 void
33849 gui_update_cursor (struct frame *f, bool on_p)
33850 {
33851 update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
33852 }
33853
33854
33855
33856
33857
33858
33859
33860 void
33861 gui_clear_cursor (struct window *w)
33862 {
33863 if (FRAME_REDISPLAY_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
33864 update_window_cursor (w, false);
33865 }
33866
33867 #endif
33868
33869
33870
33871 static void
33872 draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row,
33873 int start_hpos, int end_hpos,
33874 enum draw_glyphs_face draw)
33875 {
33876 #ifdef HAVE_WINDOW_SYSTEM
33877 if (FRAME_WINDOW_P (XFRAME (w->frame)))
33878 {
33879 draw_glyphs (w, start_x, row, TEXT_AREA, start_hpos, end_hpos, draw, 0);
33880 return;
33881 }
33882 #endif
33883
33884 #ifndef HAVE_ANDROID
33885 tty_draw_row_with_mouse_face (w, row, start_hpos, end_hpos, draw);
33886 #endif
33887 }
33888
33889
33890
33891 static void
33892 show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
33893 {
33894
33895
33896 if (!WINDOWP (hlinfo->mouse_face_window))
33897 return;
33898
33899 struct window *w = XWINDOW (hlinfo->mouse_face_window);
33900 struct frame *f = XFRAME (WINDOW_FRAME (w));
33901
33902
33903 if (f != hlinfo->mouse_face_mouse_frame)
33904 return;
33905
33906 if (
33907
33908 w->current_matrix != NULL
33909
33910 && (draw != DRAW_MOUSE_FACE || !hlinfo->mouse_face_hidden)
33911
33912
33913 && hlinfo->mouse_face_end_row < w->current_matrix->nrows)
33914 {
33915 bool phys_cursor_on_p = w->phys_cursor_on_p;
33916 #ifdef HAVE_WINDOW_SYSTEM
33917 int mouse_off = 0;
33918 #endif
33919 struct glyph_row *row, *first, *last;
33920
33921 first = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_beg_row);
33922 last = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_end_row);
33923
33924 for (row = first; row <= last && row->enabled_p; ++row)
33925 {
33926 int start_hpos, end_hpos, start_x;
33927
33928
33929 if (row == first)
33930 {
33931
33932
33933
33934
33935 if (!row->reversed_p)
33936 {
33937 start_hpos = hlinfo->mouse_face_beg_col;
33938 start_x = hlinfo->mouse_face_beg_x;
33939 }
33940 else if (row == last)
33941 {
33942 start_hpos = hlinfo->mouse_face_end_col;
33943 start_x = hlinfo->mouse_face_end_x;
33944 }
33945 else
33946 {
33947 start_hpos = 0;
33948 start_x = 0;
33949 }
33950 }
33951 else if (row->reversed_p && row == last)
33952 {
33953 start_hpos = hlinfo->mouse_face_end_col;
33954 start_x = hlinfo->mouse_face_end_x;
33955 }
33956 else
33957 {
33958 start_hpos = 0;
33959 start_x = 0;
33960 }
33961
33962 if (row == last)
33963 {
33964 if (!row->reversed_p)
33965 end_hpos = hlinfo->mouse_face_end_col;
33966 else if (row == first)
33967 end_hpos = hlinfo->mouse_face_beg_col;
33968 else
33969 {
33970 end_hpos = row->used[TEXT_AREA];
33971 if (draw == DRAW_NORMAL_TEXT)
33972 row->fill_line_p = true;
33973 }
33974 }
33975 else if (row->reversed_p && row == first)
33976 end_hpos = hlinfo->mouse_face_beg_col;
33977 else
33978 {
33979 end_hpos = row->used[TEXT_AREA];
33980 if (draw == DRAW_NORMAL_TEXT)
33981 row->fill_line_p = true;
33982 }
33983
33984 if (end_hpos > start_hpos)
33985 {
33986 draw_row_with_mouse_face (w, start_x, row,
33987 start_hpos, end_hpos, draw);
33988
33989 row->mouse_face_p
33990 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
33991 }
33992 #ifdef HAVE_WINDOW_SYSTEM
33993
33994 if ((MATRIX_ROW_VPOS (row, w->current_matrix) == w->phys_cursor.vpos)
33995
33996
33997 && !w->pseudo_window_p
33998 && draw == DRAW_MOUSE_FACE)
33999 get_cursor_offset_for_mouse_face (w, row, &mouse_off);
34000 #endif
34001 }
34002
34003
34004
34005 if (FRAME_WINDOW_P (f)
34006 && phys_cursor_on_p && !w->phys_cursor_on_p)
34007 {
34008 #ifdef HAVE_WINDOW_SYSTEM
34009 int hpos = w->phys_cursor.hpos;
34010 int old_phys_cursor_x = w->phys_cursor.x;
34011
34012
34013
34014
34015 if (!row->reversed_p && hpos < 0)
34016 hpos = 0;
34017 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
34018 hpos = row->used[TEXT_AREA] - 1;
34019
34020 block_input ();
34021 display_and_set_cursor (w, true, hpos, w->phys_cursor.vpos,
34022 w->phys_cursor.x + mouse_off,
34023 w->phys_cursor.y);
34024
34025
34026 w->phys_cursor.x = old_phys_cursor_x;
34027 unblock_input ();
34028 #endif
34029 }
34030 }
34031
34032 #ifdef HAVE_WINDOW_SYSTEM
34033
34034 if (FRAME_WINDOW_P (f) && NILP (track_mouse))
34035 {
34036 if (draw == DRAW_NORMAL_TEXT
34037 #ifndef HAVE_EXT_TOOL_BAR
34038 && !EQ (hlinfo->mouse_face_window, f->tool_bar_window)
34039 #endif
34040 && !EQ (hlinfo->mouse_face_window, f->tab_bar_window))
34041 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->text_cursor);
34042 else
34043 if (draw == DRAW_MOUSE_FACE)
34044 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->hand_cursor);
34045 else
34046 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->nontext_cursor);
34047 }
34048 #endif
34049 }
34050
34051
34052
34053
34054
34055
34056 bool
34057 clear_mouse_face (Mouse_HLInfo *hlinfo)
34058 {
34059 bool cleared
34060 = !hlinfo->mouse_face_hidden && !NILP (hlinfo->mouse_face_window);
34061 if (cleared)
34062 show_mouse_face (hlinfo, DRAW_NORMAL_TEXT);
34063 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
34064 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
34065 hlinfo->mouse_face_window = Qnil;
34066 hlinfo->mouse_face_overlay = Qnil;
34067 return cleared;
34068 }
34069
34070
34071
34072 static bool
34073 coords_in_mouse_face_p (struct window *w, int hpos, int vpos)
34074 {
34075 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
34076
34077
34078 if (!(WINDOWP (hlinfo->mouse_face_window)
34079 && XWINDOW (hlinfo->mouse_face_window) == w))
34080 return false;
34081 if (vpos < hlinfo->mouse_face_beg_row
34082 || vpos > hlinfo->mouse_face_end_row)
34083 return false;
34084 if (vpos > hlinfo->mouse_face_beg_row
34085 && vpos < hlinfo->mouse_face_end_row)
34086 return true;
34087
34088 if (!MATRIX_ROW (w->current_matrix, vpos)->reversed_p)
34089 {
34090 if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
34091 {
34092 if (hlinfo->mouse_face_beg_col <= hpos && hpos < hlinfo->mouse_face_end_col)
34093 return true;
34094 }
34095 else if ((vpos == hlinfo->mouse_face_beg_row
34096 && hpos >= hlinfo->mouse_face_beg_col)
34097 || (vpos == hlinfo->mouse_face_end_row
34098 && hpos < hlinfo->mouse_face_end_col))
34099 return true;
34100 }
34101 else
34102 {
34103 if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
34104 {
34105 if (hlinfo->mouse_face_end_col < hpos && hpos <= hlinfo->mouse_face_beg_col)
34106 return true;
34107 }
34108 else if ((vpos == hlinfo->mouse_face_beg_row
34109 && hpos <= hlinfo->mouse_face_beg_col)
34110 || (vpos == hlinfo->mouse_face_end_row
34111 && hpos > hlinfo->mouse_face_end_col))
34112 return true;
34113 }
34114 return false;
34115 }
34116
34117
34118
34119
34120
34121 bool
34122 cursor_in_mouse_face_p (struct window *w)
34123 {
34124 int vpos = w->phys_cursor.vpos;
34125
34126
34127
34128 if (!(0 <= vpos && vpos < w->current_matrix->nrows))
34129 return false;
34130
34131 int hpos = w->phys_cursor.hpos;
34132 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
34133
34134
34135
34136
34137 if (!row->reversed_p && hpos < 0)
34138 hpos = 0;
34139 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
34140 hpos = row->used[TEXT_AREA] - 1;
34141
34142 return coords_in_mouse_face_p (w, hpos, vpos);
34143 }
34144
34145
34146
34147
34148
34149
34150
34151
34152
34153 static void
34154 rows_from_pos_range (struct window *w,
34155 ptrdiff_t start_charpos, ptrdiff_t end_charpos,
34156 Lisp_Object disp_string,
34157 struct glyph_row **start, struct glyph_row **end)
34158 {
34159 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34160 int last_y = window_text_bottom_y (w);
34161 struct glyph_row *row;
34162
34163 *start = NULL;
34164 *end = NULL;
34165
34166 while (!first->enabled_p
34167 && first < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w))
34168 first++;
34169
34170
34171 for (row = first;
34172 row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y;
34173 row++)
34174 {
34175
34176
34177
34178 if (! ((start_charpos < MATRIX_ROW_START_CHARPOS (row)
34179 && end_charpos < MATRIX_ROW_START_CHARPOS (row))
34180
34181
34182
34183
34184 || ((start_charpos > MATRIX_ROW_END_CHARPOS (row)
34185 || (start_charpos == MATRIX_ROW_END_CHARPOS (row)
34186 && !row->ends_at_zv_p
34187 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
34188 && (end_charpos > MATRIX_ROW_END_CHARPOS (row)
34189 || (end_charpos == MATRIX_ROW_END_CHARPOS (row)
34190 && !row->ends_at_zv_p
34191 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))))))
34192 {
34193
34194
34195
34196
34197
34198
34199
34200
34201
34202
34203 struct glyph *g = row->glyphs[TEXT_AREA];
34204 struct glyph *e = g + row->used[TEXT_AREA];
34205
34206 while (g < e)
34207 {
34208 if (((BUFFERP (g->object) || NILP (g->object))
34209 && start_charpos <= g->charpos && g->charpos < end_charpos)
34210
34211
34212 || EQ (g->object, disp_string))
34213 *start = row;
34214 g++;
34215 }
34216 if (*start)
34217 break;
34218 }
34219 }
34220
34221
34222 if (!*start
34223
34224
34225 && !(row->enabled_p
34226 && row->y < last_y && MATRIX_ROW_BOTTOM_Y (row) > last_y))
34227 row = first;
34228 for ( ; row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y; row++)
34229 {
34230 struct glyph_row *next = row + 1;
34231 ptrdiff_t next_start = MATRIX_ROW_START_CHARPOS (next);
34232
34233 if (!next->enabled_p
34234 || next >= MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)
34235
34236
34237
34238 || (start_charpos < next_start
34239 && end_charpos < next_start)
34240 || ((start_charpos > MATRIX_ROW_END_CHARPOS (next)
34241 || (start_charpos == MATRIX_ROW_END_CHARPOS (next)
34242 && !next->ends_at_zv_p
34243 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))
34244 && (end_charpos > MATRIX_ROW_END_CHARPOS (next)
34245 || (end_charpos == MATRIX_ROW_END_CHARPOS (next)
34246 && !next->ends_at_zv_p
34247 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))))
34248 {
34249 *end = row;
34250 break;
34251 }
34252 else
34253 {
34254
34255
34256
34257 struct glyph *g = next->glyphs[TEXT_AREA];
34258 struct glyph *s = g;
34259 struct glyph *e = g + next->used[TEXT_AREA];
34260
34261 while (g < e)
34262 {
34263 if (((BUFFERP (g->object) || NILP (g->object))
34264 && ((start_charpos <= g->charpos && g->charpos < end_charpos)
34265
34266
34267
34268
34269
34270 || (((!next->reversed_p && g == s)
34271 || (next->reversed_p && g == e - 1))
34272 && (g->charpos == end_charpos
34273
34274
34275 || (g->charpos == -1
34276 && !row->ends_at_zv_p
34277 && next_start == end_charpos)))))
34278
34279
34280 || EQ (g->object, disp_string))
34281 break;
34282 g++;
34283 }
34284 if (g == e)
34285 {
34286 *end = row;
34287 break;
34288 }
34289
34290
34291 else if (next->ends_at_zv_p)
34292 {
34293 *end = next;
34294 break;
34295 }
34296 }
34297 }
34298 }
34299
34300
34301
34302
34303
34304
34305
34306
34307
34308
34309 static void
34310 mouse_face_from_buffer_pos (Lisp_Object window,
34311 Mouse_HLInfo *hlinfo,
34312 ptrdiff_t mouse_charpos,
34313 ptrdiff_t start_charpos,
34314 ptrdiff_t end_charpos,
34315 Lisp_Object before_string,
34316 Lisp_Object after_string,
34317 Lisp_Object disp_string)
34318 {
34319 struct window *w = XWINDOW (window);
34320 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34321 struct glyph_row *r1, *r2;
34322 struct glyph *glyph, *end;
34323 ptrdiff_t ignore, pos;
34324 int x;
34325
34326 eassert (NILP (disp_string) || STRINGP (disp_string));
34327 eassert (NILP (before_string) || STRINGP (before_string));
34328 eassert (NILP (after_string) || STRINGP (after_string));
34329
34330
34331 rows_from_pos_range (w, start_charpos, end_charpos, disp_string, &r1, &r2);
34332 if (r1 == NULL)
34333 r1 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34334
34335
34336 if (!NILP (before_string) || !NILP (disp_string))
34337 {
34338 struct glyph_row *prev;
34339 while ((prev = r1 - 1, prev >= first)
34340 && MATRIX_ROW_END_CHARPOS (prev) == start_charpos
34341 && prev->used[TEXT_AREA] > 0)
34342 {
34343 struct glyph *beg = prev->glyphs[TEXT_AREA];
34344 glyph = beg + prev->used[TEXT_AREA];
34345 while (--glyph >= beg && NILP (glyph->object));
34346 if (glyph < beg
34347 || !(EQ (glyph->object, before_string)
34348 || EQ (glyph->object, disp_string)))
34349 break;
34350 r1 = prev;
34351 }
34352 }
34353 if (r2 == NULL)
34354 {
34355 r2 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34356 hlinfo->mouse_face_past_end = true;
34357 }
34358 else if (!NILP (after_string))
34359 {
34360
34361 struct glyph_row *next;
34362 struct glyph_row *last
34363 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34364
34365 for (next = r2 + 1;
34366 next <= last
34367 && next->used[TEXT_AREA] > 0
34368 && EQ (next->glyphs[TEXT_AREA]->object, after_string);
34369 ++next)
34370 r2 = next;
34371 }
34372
34373
34374
34375
34376
34377 if (r1->y > r2->y)
34378 {
34379 struct glyph_row *tem = r2;
34380
34381 r2 = r1;
34382 r1 = tem;
34383 }
34384
34385 hlinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (r1, w->current_matrix);
34386 hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r2, w->current_matrix);
34387
34388
34389
34390
34391
34392
34393
34394
34395
34396
34397
34398 if (!r1->reversed_p)
34399 {
34400
34401
34402 glyph = r1->glyphs[TEXT_AREA];
34403 end = glyph + r1->used[TEXT_AREA];
34404 x = r1->x;
34405
34406
34407 if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
34408 for (; glyph < end
34409 && NILP (glyph->object)
34410 && glyph->charpos < 0;
34411 ++glyph)
34412 x += glyph->pixel_width;
34413
34414
34415
34416
34417 for (; glyph < end
34418 && !NILP (glyph->object)
34419 && !EQ (glyph->object, disp_string)
34420 && !(BUFFERP (glyph->object)
34421 && (glyph->charpos >= start_charpos
34422 && glyph->charpos < end_charpos));
34423 ++glyph)
34424 {
34425
34426
34427
34428 if (EQ (glyph->object, before_string))
34429 {
34430 pos = string_buffer_position (before_string,
34431 start_charpos);
34432
34433
34434 if (!pos || (pos >= start_charpos && pos < end_charpos))
34435 break;
34436 }
34437 else if (EQ (glyph->object, after_string))
34438 {
34439 pos = string_buffer_position (after_string, end_charpos);
34440 if (!pos || (pos >= start_charpos && pos < end_charpos))
34441 break;
34442 }
34443 x += glyph->pixel_width;
34444 }
34445 hlinfo->mouse_face_beg_x = x;
34446 hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
34447 }
34448 else
34449 {
34450
34451
34452 struct glyph *g;
34453
34454 end = r1->glyphs[TEXT_AREA] - 1;
34455 glyph = end + r1->used[TEXT_AREA];
34456
34457
34458 if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
34459 for (; glyph > end
34460 && NILP (glyph->object)
34461 && glyph->charpos < 0;
34462 --glyph)
34463 ;
34464
34465
34466
34467
34468 for (; glyph > end
34469 && !NILP (glyph->object)
34470 && !EQ (glyph->object, disp_string)
34471 && !(BUFFERP (glyph->object)
34472 && (glyph->charpos >= start_charpos
34473 && glyph->charpos < end_charpos));
34474 --glyph)
34475 {
34476
34477
34478
34479 if (EQ (glyph->object, before_string))
34480 {
34481 pos = string_buffer_position (before_string, start_charpos);
34482
34483
34484 if (!pos || (pos >= start_charpos && pos < end_charpos))
34485 break;
34486 }
34487 else if (EQ (glyph->object, after_string))
34488 {
34489 pos = string_buffer_position (after_string, end_charpos);
34490 if (!pos || (pos >= start_charpos && pos < end_charpos))
34491 break;
34492 }
34493 }
34494
34495 glyph++;
34496 for (g = r1->glyphs[TEXT_AREA], x = r1->x; g < glyph; g++)
34497 x += g->pixel_width;
34498 hlinfo->mouse_face_beg_x = x;
34499 hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
34500 }
34501
34502
34503
34504
34505 if (r2 != r1)
34506 {
34507 if (!r2->reversed_p)
34508 {
34509 glyph = r2->glyphs[TEXT_AREA];
34510 end = glyph + r2->used[TEXT_AREA];
34511 x = r2->x;
34512 }
34513 else
34514 {
34515 end = r2->glyphs[TEXT_AREA] - 1;
34516 glyph = end + r2->used[TEXT_AREA];
34517 }
34518 }
34519
34520 if (!r2->reversed_p)
34521 {
34522
34523
34524
34525 while (end > glyph
34526 && NILP ((end - 1)->object))
34527 --end;
34528
34529
34530
34531
34532 for (--end;
34533 end > glyph
34534 && !NILP (end->object)
34535 && !EQ (end->object, disp_string)
34536 && !(BUFFERP (end->object)
34537 && (end->charpos >= start_charpos
34538 && end->charpos < end_charpos));
34539 --end)
34540 {
34541
34542
34543
34544 if (EQ (end->object, before_string))
34545 {
34546 pos = string_buffer_position (before_string, start_charpos);
34547 if (!pos || (pos >= start_charpos && pos < end_charpos))
34548 break;
34549 }
34550 else if (EQ (end->object, after_string))
34551 {
34552 pos = string_buffer_position (after_string, end_charpos);
34553 if (!pos || (pos >= start_charpos && pos < end_charpos))
34554 break;
34555 }
34556 }
34557
34558 for (; glyph <= end; ++glyph)
34559 x += glyph->pixel_width;
34560
34561 hlinfo->mouse_face_end_x = x;
34562 hlinfo->mouse_face_end_col = glyph - r2->glyphs[TEXT_AREA];
34563 }
34564 else
34565 {
34566
34567
34568
34569 x = r2->x;
34570 end++;
34571 while (end < glyph
34572 && NILP (end->object))
34573 {
34574 x += end->pixel_width;
34575 ++end;
34576 }
34577
34578
34579
34580
34581 for ( ;
34582 end < glyph
34583 && !NILP (end->object)
34584 && !EQ (end->object, disp_string)
34585 && !(BUFFERP (end->object)
34586 && (end->charpos >= start_charpos
34587 && end->charpos < end_charpos));
34588 ++end)
34589 {
34590
34591
34592
34593 if (EQ (end->object, before_string))
34594 {
34595 pos = string_buffer_position (before_string, start_charpos);
34596 if (!pos || (pos >= start_charpos && pos < end_charpos))
34597 break;
34598 }
34599 else if (EQ (end->object, after_string))
34600 {
34601 pos = string_buffer_position (after_string, end_charpos);
34602 if (!pos || (pos >= start_charpos && pos < end_charpos))
34603 break;
34604 }
34605 x += end->pixel_width;
34606 }
34607
34608
34609
34610
34611
34612 if (end == glyph
34613 && BUFFERP (end->object)
34614 && (end->charpos < start_charpos
34615 || end->charpos >= end_charpos))
34616 {
34617 x += end->pixel_width;
34618 ++end;
34619 }
34620 hlinfo->mouse_face_end_x = x;
34621 hlinfo->mouse_face_end_col = end - r2->glyphs[TEXT_AREA];
34622 }
34623
34624 hlinfo->mouse_face_window = window;
34625 hlinfo->mouse_face_face_id
34626 = face_at_buffer_position (w, mouse_charpos, &ignore,
34627 mouse_charpos + 1,
34628 !hlinfo->mouse_face_hidden, -1, 0);
34629 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
34630 }
34631
34632
34633
34634
34635
34636 #if false
34637
34638
34639
34640
34641
34642
34643
34644
34645
34646
34647
34648
34649
34650
34651
34652
34653 static bool
34654 fast_find_string_pos (struct window *w, ptrdiff_t pos, Lisp_Object object,
34655 int *hpos, int *vpos, int *x, int *y, bool right_p)
34656 {
34657 int yb = window_text_bottom_y (w);
34658 struct glyph_row *r;
34659 struct glyph *best_glyph = NULL;
34660 struct glyph_row *best_row = NULL;
34661 int best_x = 0;
34662
34663 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34664 r->enabled_p && r->y < yb;
34665 ++r)
34666 {
34667 struct glyph *g = r->glyphs[TEXT_AREA];
34668 struct glyph *e = g + r->used[TEXT_AREA];
34669 int gx;
34670
34671 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
34672 if (EQ (g->object, object))
34673 {
34674 if (g->charpos == pos)
34675 {
34676 best_glyph = g;
34677 best_x = gx;
34678 best_row = r;
34679 goto found;
34680 }
34681 else if (best_glyph == NULL
34682 || ((eabs (g->charpos - pos)
34683 < eabs (best_glyph->charpos - pos))
34684 && (right_p
34685 ? g->charpos < pos
34686 : g->charpos > pos)))
34687 {
34688 best_glyph = g;
34689 best_x = gx;
34690 best_row = r;
34691 }
34692 }
34693 }
34694
34695 found:
34696
34697 if (best_glyph)
34698 {
34699 *x = best_x;
34700 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
34701
34702 if (right_p)
34703 {
34704 *x += best_glyph->pixel_width;
34705 ++*hpos;
34706 }
34707
34708 *y = best_row->y;
34709 *vpos = MATRIX_ROW_VPOS (best_row, w->current_matrix);
34710 }
34711
34712 return best_glyph != NULL;
34713 }
34714 #endif
34715
34716
34717
34718
34719
34720
34721 static void
34722 mouse_face_from_string_pos (struct window *w, Mouse_HLInfo *hlinfo,
34723 Lisp_Object object,
34724 ptrdiff_t startpos, ptrdiff_t endpos)
34725 {
34726 int yb = window_text_bottom_y (w);
34727 struct glyph_row *r;
34728 struct glyph *g, *e;
34729 int gx;
34730 bool found = false;
34731
34732
34733
34734
34735 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34736 r->enabled_p && r->y < yb;
34737 ++r)
34738 {
34739 if (!r->reversed_p)
34740 {
34741 g = r->glyphs[TEXT_AREA];
34742 e = g + r->used[TEXT_AREA];
34743 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
34744 if (EQ (g->object, object)
34745 && startpos <= g->charpos && g->charpos < endpos)
34746 {
34747 hlinfo->mouse_face_beg_row
34748 = MATRIX_ROW_VPOS (r, w->current_matrix);
34749 hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
34750 hlinfo->mouse_face_beg_x = gx;
34751 found = true;
34752 break;
34753 }
34754 }
34755 else
34756 {
34757 struct glyph *g1;
34758
34759 e = r->glyphs[TEXT_AREA];
34760 g = e + r->used[TEXT_AREA];
34761 for ( ; g > e; --g)
34762 if (EQ ((g-1)->object, object)
34763 && startpos <= (g-1)->charpos && (g-1)->charpos < endpos)
34764 {
34765 hlinfo->mouse_face_beg_row
34766 = MATRIX_ROW_VPOS (r, w->current_matrix);
34767 hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
34768 for (gx = r->x, g1 = r->glyphs[TEXT_AREA]; g1 < g; ++g1)
34769 gx += g1->pixel_width;
34770 hlinfo->mouse_face_beg_x = gx;
34771 found = true;
34772 break;
34773 }
34774 }
34775 if (found)
34776 break;
34777 }
34778
34779 if (!found)
34780 return;
34781
34782
34783
34784 for (++r; r->enabled_p && r->y < yb; ++r)
34785 {
34786 g = r->glyphs[TEXT_AREA];
34787 e = g + r->used[TEXT_AREA];
34788 found = false;
34789 for ( ; g < e; ++g)
34790 if (EQ (g->object, object)
34791 && startpos <= g->charpos && g->charpos < endpos)
34792 {
34793 found = true;
34794 break;
34795 }
34796 if (!found)
34797 break;
34798 }
34799
34800
34801 r--;
34802
34803
34804 hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r, w->current_matrix);
34805
34806
34807
34808 if (!r->reversed_p)
34809 {
34810 g = r->glyphs[TEXT_AREA];
34811 e = g + r->used[TEXT_AREA];
34812 for ( ; e > g; --e)
34813 if (EQ ((e-1)->object, object)
34814 && startpos <= (e-1)->charpos && (e-1)->charpos < endpos)
34815 break;
34816 hlinfo->mouse_face_end_col = e - g;
34817
34818 for (gx = r->x; g < e; ++g)
34819 gx += g->pixel_width;
34820 hlinfo->mouse_face_end_x = gx;
34821 }
34822 else
34823 {
34824 e = r->glyphs[TEXT_AREA];
34825 g = e + r->used[TEXT_AREA];
34826 for (gx = r->x ; e < g; ++e)
34827 {
34828 if (EQ (e->object, object)
34829 && startpos <= e->charpos && e->charpos < endpos)
34830 break;
34831 gx += e->pixel_width;
34832 }
34833 hlinfo->mouse_face_end_col = e - r->glyphs[TEXT_AREA];
34834 hlinfo->mouse_face_end_x = gx;
34835 }
34836 }
34837
34838 #ifdef HAVE_WINDOW_SYSTEM
34839
34840
34841
34842 static bool
34843 on_hot_spot_p (Lisp_Object hot_spot, int x, int y)
34844 {
34845 if (!CONSP (hot_spot))
34846 return false;
34847
34848 if (EQ (XCAR (hot_spot), Qrect))
34849 {
34850
34851 Lisp_Object rect = XCDR (hot_spot);
34852 Lisp_Object tem;
34853 if (!CONSP (rect))
34854 return false;
34855 if (!CONSP (XCAR (rect)))
34856 return false;
34857 if (!CONSP (XCDR (rect)))
34858 return false;
34859 if (!(tem = XCAR (XCAR (rect)), FIXNUMP (tem) && x >= XFIXNUM (tem)))
34860 return false;
34861 if (!(tem = XCDR (XCAR (rect)), FIXNUMP (tem) && y >= XFIXNUM (tem)))
34862 return false;
34863 if (!(tem = XCAR (XCDR (rect)), FIXNUMP (tem) && x <= XFIXNUM (tem)))
34864 return false;
34865 if (!(tem = XCDR (XCDR (rect)), FIXNUMP (tem) && y <= XFIXNUM (tem)))
34866 return false;
34867 return true;
34868 }
34869 else if (EQ (XCAR (hot_spot), Qcircle))
34870 {
34871
34872 Lisp_Object circ = XCDR (hot_spot);
34873 Lisp_Object lr, lx0, ly0;
34874 if (CONSP (circ)
34875 && CONSP (XCAR (circ))
34876 && (lr = XCDR (circ), NUMBERP (lr))
34877 && (lx0 = XCAR (XCAR (circ)), FIXNUMP (lx0))
34878 && (ly0 = XCDR (XCAR (circ)), FIXNUMP (ly0)))
34879 {
34880 double r = XFLOATINT (lr);
34881 double dx = XFIXNUM (lx0) - x;
34882 double dy = XFIXNUM (ly0) - y;
34883 return (dx * dx + dy * dy <= r * r);
34884 }
34885 }
34886 else if (EQ (XCAR (hot_spot), Qpoly))
34887 {
34888
34889 if (VECTORP (XCDR (hot_spot)))
34890 {
34891 struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot));
34892 Lisp_Object *poly = v->contents;
34893 ptrdiff_t n = v->header.size;
34894 ptrdiff_t i;
34895 bool inside = false;
34896 Lisp_Object lx, ly;
34897 int x0, y0;
34898
34899
34900 if (n < 6 || n & 1)
34901 return false;
34902
34903
34904
34905
34906
34907 if ((lx = poly[n-2], !FIXNUMP (lx))
34908 || (ly = poly[n-1], !FIXNUMP (lx)))
34909 return false;
34910 x0 = XFIXNUM (lx), y0 = XFIXNUM (ly);
34911 for (i = 0; i < n; i += 2)
34912 {
34913 int x1 = x0, y1 = y0;
34914 if ((lx = poly[i], !FIXNUMP (lx))
34915 || (ly = poly[i+1], !FIXNUMP (ly)))
34916 return false;
34917 x0 = XFIXNUM (lx), y0 = XFIXNUM (ly);
34918
34919
34920 if (x0 >= x)
34921 {
34922 if (x1 >= x)
34923 continue;
34924 }
34925 else if (x1 < x)
34926 continue;
34927 if (y > y0 && y > y1)
34928 continue;
34929 if (y < y0 + ((y1 - y0) * (x - x0)) / (x1 - x0))
34930 inside = !inside;
34931 }
34932 return inside;
34933 }
34934 }
34935 return false;
34936 }
34937
34938 Lisp_Object
34939 find_hot_spot (Lisp_Object map, int x, int y)
34940 {
34941 while (CONSP (map))
34942 {
34943 if (CONSP (XCAR (map))
34944 && on_hot_spot_p (XCAR (XCAR (map)), x, y))
34945 return XCAR (map);
34946 map = XCDR (map);
34947 }
34948
34949 return Qnil;
34950 }
34951
34952 DEFUN ("lookup-image-map", Flookup_image_map, Slookup_image_map,
34953 3, 3, 0,
34954 doc:
34955
34956
34957
34958
34959
34960
34961
34962
34963 )
34964 (Lisp_Object map, Lisp_Object x, Lisp_Object y)
34965 {
34966 if (NILP (map))
34967 return Qnil;
34968
34969 CHECK_FIXNUM (x);
34970 CHECK_FIXNUM (y);
34971
34972 return find_hot_spot (map,
34973 clip_to_bounds (INT_MIN, XFIXNUM (x), INT_MAX),
34974 clip_to_bounds (INT_MIN, XFIXNUM (y), INT_MAX));
34975 }
34976 #endif
34977
34978
34979
34980 static void
34981 define_frame_cursor1 (struct frame *f, Emacs_Cursor cursor, Lisp_Object pointer)
34982 {
34983 #ifdef HAVE_WINDOW_SYSTEM
34984 if (!FRAME_WINDOW_P (f))
34985 return;
34986
34987
34988 if (EQ (track_mouse, Qdragging) || EQ (track_mouse, Qdropping)
34989 || EQ (track_mouse, Qdrag_source))
34990 return;
34991
34992 if (!NILP (pointer))
34993 {
34994 if (EQ (pointer, Qarrow))
34995 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34996 else if (EQ (pointer, Qhand))
34997 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
34998 else if (EQ (pointer, Qtext))
34999 cursor = FRAME_OUTPUT_DATA (f)->text_cursor;
35000 else if (EQ (pointer, intern ("hdrag")))
35001 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35002 else if (EQ (pointer, intern ("nhdrag")))
35003 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35004 # ifdef HAVE_X_WINDOWS
35005 else if (EQ (pointer, intern ("vdrag")))
35006 cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
35007 # endif
35008 else if (EQ (pointer, intern ("hourglass")))
35009 cursor = FRAME_OUTPUT_DATA (f)->hourglass_cursor;
35010 else if (EQ (pointer, Qmodeline))
35011 cursor = FRAME_OUTPUT_DATA (f)->modeline_cursor;
35012 else
35013 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35014 }
35015
35016 if (cursor != No_Cursor)
35017 FRAME_RIF (f)->define_frame_cursor (f, cursor);
35018 #endif
35019 }
35020
35021
35022
35023
35024
35025
35026
35027 static void
35028 note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
35029 enum window_part area)
35030 {
35031 struct window *w = XWINDOW (window);
35032 struct frame *f = XFRAME (w->frame);
35033 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
35034 Emacs_Cursor cursor = No_Cursor;
35035 Lisp_Object pointer = Qnil;
35036 int dx, dy, width, height;
35037 ptrdiff_t charpos;
35038 Lisp_Object string, object = Qnil;
35039 Lisp_Object pos UNINIT;
35040 Lisp_Object mouse_face;
35041 int original_x_pixel = x;
35042 struct glyph * glyph = NULL, * row_start_glyph = NULL;
35043 struct glyph_row *row UNINIT;
35044
35045 if (area == ON_MODE_LINE || area == ON_HEADER_LINE || area == ON_TAB_LINE)
35046 {
35047 int x0;
35048 struct glyph *end;
35049
35050
35051
35052 string = mode_line_string (w, area, &x, &y, &charpos,
35053 &object, &dx, &dy, &width, &height);
35054
35055 row = (area == ON_MODE_LINE
35056 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
35057 : (area == ON_TAB_LINE
35058 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
35059 : MATRIX_HEADER_LINE_ROW (w->current_matrix)));
35060
35061
35062 if (row->mode_line_p && row->enabled_p)
35063 {
35064 glyph = row_start_glyph = row->glyphs[TEXT_AREA];
35065 end = glyph + row->used[TEXT_AREA];
35066
35067 for (x0 = original_x_pixel;
35068 glyph < end && x0 >= glyph->pixel_width;
35069 ++glyph)
35070 x0 -= glyph->pixel_width;
35071
35072 if (glyph >= end)
35073 glyph = NULL;
35074 }
35075 }
35076 else
35077 {
35078 x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
35079
35080
35081 string = marginal_area_string (w, area, &x, &y, &charpos,
35082 &object, &dx, &dy, &width, &height);
35083 }
35084
35085 Lisp_Object help = Qnil;
35086
35087 #ifdef HAVE_WINDOW_SYSTEM
35088 if (IMAGEP (object))
35089 {
35090 Lisp_Object image_map, hotspot;
35091 if ((image_map = plist_get (XCDR (object), QCmap),
35092 !NILP (image_map))
35093 && (hotspot = find_hot_spot (image_map, dx, dy),
35094 CONSP (hotspot))
35095 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
35096 {
35097 Lisp_Object plist;
35098
35099
35100
35101
35102 hotspot = XCDR (hotspot);
35103 if (CONSP (hotspot)
35104 && (plist = XCAR (hotspot), CONSP (plist)))
35105 {
35106 pointer = plist_get (plist, Qpointer);
35107 if (NILP (pointer))
35108 pointer = Qhand;
35109 help = plist_get (plist, Qhelp_echo);
35110 if (!NILP (help))
35111 {
35112 help_echo_string = help;
35113 XSETWINDOW (help_echo_window, w);
35114 help_echo_object = w->contents;
35115 help_echo_pos = charpos;
35116 }
35117 }
35118 }
35119 if (NILP (pointer))
35120 pointer = plist_get (XCDR (object), QCpointer);
35121 }
35122 #endif
35123
35124
35125
35126
35127 if (STRINGP (string))
35128 pos = make_fixnum (min (charpos, SCHARS (string) - 1));
35129
35130
35131
35132
35133
35134 if (STRINGP (string) || area == ON_MODE_LINE || area == ON_HEADER_LINE
35135 || area == ON_TAB_LINE)
35136 {
35137
35138
35139 if (NILP (help))
35140 {
35141 if (STRINGP (string))
35142 help = Fget_text_property (pos, Qhelp_echo, string);
35143
35144 if (!NILP (help))
35145 {
35146 help_echo_string = help;
35147 XSETWINDOW (help_echo_window, w);
35148 help_echo_object = string;
35149 help_echo_pos = charpos;
35150 }
35151 else if (area == ON_MODE_LINE
35152 && !NILP (w->mode_line_help_echo))
35153 {
35154 help_echo_string = w->mode_line_help_echo;
35155 XSETWINDOW (help_echo_window, w);
35156 help_echo_object = Qnil;
35157 help_echo_pos = -1;
35158 }
35159 }
35160
35161 #ifdef HAVE_WINDOW_SYSTEM
35162
35163 if (FRAME_WINDOW_P (f))
35164 {
35165 bool draggable = (! WINDOW_BOTTOMMOST_P (w)
35166 || minibuf_level
35167 || NILP (Vresize_mini_windows));
35168
35169 if (STRINGP (string))
35170 {
35171 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35172
35173 if (NILP (pointer))
35174 pointer = Fget_text_property (pos, Qpointer, string);
35175
35176
35177 if (NILP (pointer)
35178 && (area == ON_MODE_LINE || area == ON_HEADER_LINE
35179 || area == ON_TAB_LINE))
35180 {
35181 Lisp_Object map;
35182
35183 map = Fget_text_property (pos, Qlocal_map, string);
35184 if (!KEYMAPP (map))
35185 map = Fget_text_property (pos, Qkeymap, string);
35186 if (!KEYMAPP (map) && draggable && area == ON_MODE_LINE)
35187 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35188 }
35189 }
35190 else if (draggable && area == ON_MODE_LINE)
35191 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35192 else if ((area == ON_MODE_LINE
35193 && WINDOW_BOTTOMMOST_P (w)
35194 && !FRAME_HAS_MINIBUF_P (f)
35195 && !NILP (Fframe_parameter
35196 (w->frame, Qdrag_with_mode_line)))
35197 || (((area == ON_HEADER_LINE
35198 && !NILP (Fframe_parameter
35199 (w->frame, Qdrag_with_header_line)))
35200 || (area == ON_TAB_LINE
35201 && !NILP (Fframe_parameter
35202 (w->frame, Qdrag_with_tab_line))))
35203 && WINDOW_TOPMOST_P (w)))
35204 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
35205 else
35206 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35207 }
35208 #endif
35209 }
35210
35211
35212 bool mouse_face_shown = false;
35213
35214 if (STRINGP (string))
35215 {
35216 mouse_face = Fget_text_property (pos, Qmouse_face, string);
35217 if (!NILP (Vmouse_highlight) && !NILP (mouse_face)
35218 && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE)
35219 || (area == ON_TAB_LINE))
35220 && glyph)
35221 {
35222 Lisp_Object b, e;
35223
35224 struct glyph * tmp_glyph;
35225
35226 int gpos;
35227 int gseq_length;
35228 int total_pixel_width;
35229 ptrdiff_t begpos, endpos, ignore;
35230
35231 int vpos, hpos;
35232
35233 b = Fprevious_single_property_change (make_fixnum (charpos + 1),
35234 Qmouse_face, string, Qnil);
35235 if (NILP (b))
35236 begpos = 0;
35237 else
35238 begpos = XFIXNUM (b);
35239
35240 e = Fnext_single_property_change (pos, Qmouse_face, string, Qnil);
35241 if (NILP (e))
35242 endpos = SCHARS (string);
35243 else
35244 endpos = XFIXNUM (e);
35245
35246
35247
35248
35249
35250
35251
35252
35253
35254
35255
35256 tmp_glyph = row_start_glyph;
35257 while (tmp_glyph < glyph
35258 && (!(EQ (tmp_glyph->object, glyph->object)
35259 && begpos <= tmp_glyph->charpos
35260 && tmp_glyph->charpos < endpos)))
35261 tmp_glyph++;
35262 gpos = glyph - tmp_glyph;
35263
35264
35265
35266
35267
35268
35269 for (tmp_glyph = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
35270 tmp_glyph > glyph
35271 && (!(EQ (tmp_glyph->object, glyph->object)
35272 && begpos <= tmp_glyph->charpos
35273 && tmp_glyph->charpos < endpos));
35274 tmp_glyph--)
35275 ;
35276 gseq_length = gpos + (tmp_glyph - glyph) + 1;
35277
35278
35279
35280 total_pixel_width = 0;
35281 for (tmp_glyph = glyph - gpos; tmp_glyph != glyph; tmp_glyph++)
35282 total_pixel_width += tmp_glyph->pixel_width;
35283
35284
35285
35286
35287 hpos = x - gpos;
35288 vpos = (area == ON_MODE_LINE
35289 ? (w->current_matrix)->nrows - 1
35290 : (area == ON_TAB_LINE
35291 ? 0
35292 : (w->current_matrix->tab_line_p
35293 ? 1
35294 : 0)));
35295
35296
35297
35298 if ( EQ (window, hlinfo->mouse_face_window)
35299 && (!row->reversed_p
35300 ? (hlinfo->mouse_face_beg_col <= hpos
35301 && hpos < hlinfo->mouse_face_end_col)
35302
35303 : (hlinfo->mouse_face_end_col <= hpos
35304 && hpos < hlinfo->mouse_face_beg_col))
35305 && hlinfo->mouse_face_beg_row == vpos )
35306 return;
35307
35308 if (clear_mouse_face (hlinfo))
35309 cursor = No_Cursor;
35310
35311 if (!row->reversed_p)
35312 {
35313 hlinfo->mouse_face_beg_col = hpos;
35314 hlinfo->mouse_face_beg_x = original_x_pixel
35315 - (total_pixel_width + dx);
35316 hlinfo->mouse_face_end_col = hpos + gseq_length;
35317 hlinfo->mouse_face_end_x = 0;
35318 }
35319 else
35320 {
35321
35322
35323 hlinfo->mouse_face_end_col = hpos;
35324 hlinfo->mouse_face_end_x = original_x_pixel
35325 - (total_pixel_width + dx);
35326 hlinfo->mouse_face_beg_col = hpos + gseq_length;
35327 hlinfo->mouse_face_beg_x = 0;
35328 }
35329
35330 hlinfo->mouse_face_beg_row = vpos;
35331 hlinfo->mouse_face_end_row = hlinfo->mouse_face_beg_row;
35332 hlinfo->mouse_face_past_end = false;
35333 hlinfo->mouse_face_window = window;
35334
35335 hlinfo->mouse_face_face_id =
35336 face_at_string_position (w, string, charpos, 0, &ignore,
35337 glyph->face_id, true, 0);
35338
35339 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
35340 mouse_face_shown = true;
35341
35342 if (NILP (pointer))
35343 pointer = Qhand;
35344 }
35345 }
35346
35347
35348
35349 if ((area == ON_MODE_LINE || area == ON_HEADER_LINE
35350 || area == ON_TAB_LINE) && !mouse_face_shown)
35351 clear_mouse_face (hlinfo);
35352
35353 define_frame_cursor1 (f, cursor, pointer);
35354 }
35355
35356
35357
35358
35359
35360
35361
35362
35363
35364
35365 void
35366 note_mouse_highlight (struct frame *f, int x, int y)
35367 {
35368 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
35369 enum window_part part = ON_NOTHING;
35370 Lisp_Object window;
35371 struct window *w;
35372 Emacs_Cursor cursor = No_Cursor;
35373 Lisp_Object pointer = Qnil;
35374 struct buffer *b;
35375
35376
35377 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NS) || defined (MSDOS) \
35378 || defined (HAVE_ANDROID)
35379 if (popup_activated ())
35380 return;
35381 #endif
35382
35383 #if defined (HAVE_HAIKU)
35384 if (popup_activated_p)
35385 return;
35386 #endif
35387
35388 if (!f->glyphs_initialized_p
35389 || f->pointer_invisible)
35390 return;
35391
35392 hlinfo->mouse_face_mouse_x = x;
35393 hlinfo->mouse_face_mouse_y = y;
35394 hlinfo->mouse_face_mouse_frame = f;
35395
35396 if (hlinfo->mouse_face_defer)
35397 return;
35398
35399
35400 window = window_from_coordinates (f, x, y, &part, true, true);
35401
35402
35403 if (! EQ (window, hlinfo->mouse_face_window)
35404
35405 || (!NILP (hlinfo->mouse_face_window)
35406 && !NILP (window)
35407 && part != ON_TEXT
35408 && part != ON_MODE_LINE
35409 && part != ON_HEADER_LINE
35410 && part != ON_TAB_LINE))
35411 clear_mouse_face (hlinfo);
35412
35413
35414 help_echo_string = Qnil;
35415
35416
35417 if (!FRAME_WINDOW_P (f)
35418 && (y >= FRAME_MENU_BAR_LINES (f)
35419 && y < FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f)))
35420 {
35421 int prop_idx;
35422 bool ignore;
35423 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &ignore);
35424
35425 if (!NILP (caption))
35426 {
35427 help_echo_object = help_echo_window = Qnil;
35428 help_echo_pos = -1;
35429 help_echo_string = AREF (f->tab_bar_items,
35430 prop_idx * TAB_BAR_ITEM_NSLOTS
35431 + TAB_BAR_ITEM_HELP);
35432 if (NILP (help_echo_string))
35433 help_echo_string = caption;
35434 }
35435 }
35436
35437 #ifdef HAVE_WINDOW_SYSTEM
35438
35439
35440 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0
35441 && !NILP (get_frame_param (f, Qdrag_internal_border)))
35442 {
35443 enum internal_border_part part = frame_internal_border_part (f, x, y);
35444
35445 switch (part)
35446 {
35447 case INTERNAL_BORDER_NONE:
35448 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35449
35450 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35451 break;
35452 case INTERNAL_BORDER_LEFT_EDGE:
35453 cursor = FRAME_OUTPUT_DATA (f)->left_edge_cursor;
35454 break;
35455 case INTERNAL_BORDER_TOP_LEFT_CORNER:
35456 cursor = FRAME_OUTPUT_DATA (f)->top_left_corner_cursor;
35457 break;
35458 case INTERNAL_BORDER_TOP_EDGE:
35459 cursor = FRAME_OUTPUT_DATA (f)->top_edge_cursor;
35460 break;
35461 case INTERNAL_BORDER_TOP_RIGHT_CORNER:
35462 cursor = FRAME_OUTPUT_DATA (f)->top_right_corner_cursor;
35463 break;
35464 case INTERNAL_BORDER_RIGHT_EDGE:
35465 cursor = FRAME_OUTPUT_DATA (f)->right_edge_cursor;
35466 break;
35467 case INTERNAL_BORDER_BOTTOM_RIGHT_CORNER:
35468 cursor = FRAME_OUTPUT_DATA (f)->bottom_right_corner_cursor;
35469 break;
35470 case INTERNAL_BORDER_BOTTOM_EDGE:
35471 cursor = FRAME_OUTPUT_DATA (f)->bottom_edge_cursor;
35472 break;
35473 case INTERNAL_BORDER_BOTTOM_LEFT_CORNER:
35474 cursor = FRAME_OUTPUT_DATA (f)->bottom_left_corner_cursor;
35475 break;
35476 default:
35477
35478 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35479 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35480 }
35481
35482 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35483 {
35484
35485 help_echo_string = build_string ("drag-mouse-1: resize frame");
35486 goto set_cursor;
35487 }
35488 }
35489 #endif
35490
35491
35492 if (!WINDOWP (window))
35493 return;
35494
35495
35496 w = XWINDOW (window);
35497 frame_to_window_pixel_xy (w, &x, &y);
35498
35499 #if defined (HAVE_WINDOW_SYSTEM)
35500
35501
35502 if (EQ (window, f->tab_bar_window))
35503 {
35504 note_tab_bar_highlight (f, x, y);
35505 if (tab_bar__dragging_in_progress)
35506 {
35507 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
35508 goto set_cursor;
35509 }
35510 else
35511 return;
35512 }
35513 else
35514 {
35515
35516
35517
35518
35519 f->last_tab_bar_item = -1;
35520 }
35521 #endif
35522
35523 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
35524
35525
35526 if (EQ (window, f->tool_bar_window))
35527 {
35528 note_tool_bar_highlight (f, x, y);
35529 return;
35530 }
35531 #endif
35532
35533
35534 if (part == ON_MODE_LINE || part == ON_HEADER_LINE || part == ON_TAB_LINE
35535 || part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
35536 {
35537 note_mode_line_or_margin_highlight (window, x, y, part);
35538
35539 #ifdef HAVE_WINDOW_SYSTEM
35540 if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
35541 {
35542 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35543
35544 goto set_cursor;
35545 }
35546 else
35547 #endif
35548 return;
35549 }
35550
35551 #ifdef HAVE_WINDOW_SYSTEM
35552 if (part == ON_VERTICAL_BORDER)
35553 {
35554 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35555 help_echo_string = build_string ("drag-mouse-1: resize");
35556 goto set_cursor;
35557 }
35558 else if (part == ON_RIGHT_DIVIDER)
35559 {
35560 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35561 help_echo_string = build_string ("drag-mouse-1: resize");
35562 goto set_cursor;
35563 }
35564 else if (part == ON_BOTTOM_DIVIDER)
35565 if (! WINDOW_BOTTOMMOST_P (w)
35566 || minibuf_level
35567 || NILP (Vresize_mini_windows))
35568 {
35569 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35570 help_echo_string = build_string ("drag-mouse-1: resize");
35571 goto set_cursor;
35572 }
35573 else
35574 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35575 else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
35576 || part == ON_VERTICAL_SCROLL_BAR
35577 || part == ON_HORIZONTAL_SCROLL_BAR)
35578 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35579 else
35580 cursor = FRAME_OUTPUT_DATA (f)->text_cursor;
35581 #endif
35582
35583
35584
35585 b = XBUFFER (w->contents);
35586 if (part == ON_TEXT && w->window_end_valid && !window_outdated (w))
35587 {
35588 int hpos, vpos, dx, dy, area = LAST_AREA;
35589 ptrdiff_t pos;
35590 struct glyph *glyph;
35591 Lisp_Object object;
35592 Lisp_Object mouse_face = Qnil, position;
35593 Lisp_Object *overlay_vec = NULL;
35594 ptrdiff_t i, noverlays;
35595 struct buffer *obuf;
35596 ptrdiff_t obegv, ozv;
35597 bool same_region;
35598
35599
35600 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &dx, &dy, &area);
35601
35602 #ifdef HAVE_WINDOW_SYSTEM
35603
35604 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
35605 {
35606 struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
35607 if (img != NULL && IMAGEP (img->spec))
35608 {
35609 Lisp_Object image_map, hotspot;
35610 if ((image_map = plist_get (XCDR (img->spec), QCmap),
35611 !NILP (image_map))
35612 && (hotspot = find_hot_spot (image_map,
35613 glyph->slice.img.x + dx,
35614 glyph->slice.img.y + dy),
35615 CONSP (hotspot))
35616 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
35617 {
35618 Lisp_Object plist;
35619
35620
35621
35622
35623
35624 hotspot = XCDR (hotspot);
35625 if (CONSP (hotspot)
35626 && (plist = XCAR (hotspot), CONSP (plist)))
35627 {
35628 pointer = plist_get (plist, Qpointer);
35629 if (NILP (pointer))
35630 pointer = Qhand;
35631 help_echo_string = plist_get (plist, Qhelp_echo);
35632 if (!NILP (help_echo_string))
35633 {
35634 help_echo_window = window;
35635 help_echo_object = glyph->object;
35636 help_echo_pos = glyph->charpos;
35637 }
35638 }
35639 }
35640 if (NILP (pointer))
35641 pointer = plist_get (XCDR (img->spec), QCpointer);
35642 }
35643 }
35644 #endif
35645
35646
35647 if (glyph == NULL
35648 || area != TEXT_AREA
35649 || !MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->current_matrix, vpos))
35650
35651
35652
35653
35654
35655 || NILP (glyph->object)
35656
35657
35658
35659
35660 || (MATRIX_ROW (w->current_matrix, vpos)->reversed_p
35661 && glyph == MATRIX_ROW_GLYPH_START (w->current_matrix, vpos)
35662 && glyph->type == STRETCH_GLYPH
35663 && glyph->avoid_cursor_p))
35664 {
35665 if (clear_mouse_face (hlinfo))
35666 cursor = No_Cursor;
35667 if (FRAME_WINDOW_P (f) && NILP (pointer))
35668 {
35669 #ifdef HAVE_WINDOW_SYSTEM
35670 if (area != TEXT_AREA)
35671 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35672 else
35673 pointer = Vvoid_text_area_pointer;
35674 #endif
35675 }
35676 goto set_cursor;
35677 }
35678
35679 pos = glyph->charpos;
35680 object = glyph->object;
35681 if (!STRINGP (object) && !BUFFERP (object))
35682 goto set_cursor;
35683
35684
35685 if (BUFFERP (object) && pos > BUF_Z (b))
35686 goto set_cursor;
35687
35688
35689
35690 obuf = current_buffer;
35691 current_buffer = b;
35692 obegv = BEGV;
35693 ozv = ZV;
35694 BEGV = BEG;
35695 ZV = Z;
35696
35697
35698 position = make_fixnum (pos);
35699
35700 USE_SAFE_ALLOCA;
35701
35702 if (BUFFERP (object))
35703 {
35704
35705 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL);
35706
35707 noverlays = sort_overlays (overlay_vec, noverlays, w);
35708 }
35709 else
35710 noverlays = 0;
35711
35712 if (NILP (Vmouse_highlight))
35713 {
35714 clear_mouse_face (hlinfo);
35715 goto check_help_echo;
35716 }
35717
35718 same_region = coords_in_mouse_face_p (w, hpos, vpos);
35719
35720 if (same_region)
35721 cursor = No_Cursor;
35722
35723
35724 if (! same_region
35725
35726
35727
35728
35729
35730 || (!hlinfo->mouse_face_hidden
35731 && OVERLAYP (hlinfo->mouse_face_overlay)
35732
35733 && OVERLAY_BUFFER (hlinfo->mouse_face_overlay)
35734 && mouse_face_overlay_overlaps (hlinfo->mouse_face_overlay)))
35735 {
35736
35737 Lisp_Object overlay = Qnil;
35738 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
35739 {
35740 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
35741 if (!NILP (mouse_face))
35742 overlay = overlay_vec[i];
35743 }
35744
35745
35746
35747 if (!NILP (overlay) && EQ (overlay, hlinfo->mouse_face_overlay))
35748 goto check_help_echo;
35749
35750
35751 if (clear_mouse_face (hlinfo))
35752 cursor = No_Cursor;
35753
35754
35755 hlinfo->mouse_face_overlay = overlay;
35756
35757
35758 if (NILP (overlay))
35759 mouse_face = Fget_text_property (position, Qmouse_face, object);
35760
35761
35762
35763 if (!NILP (mouse_face) && STRINGP (object))
35764 {
35765
35766
35767 Lisp_Object s, e;
35768 ptrdiff_t ignore;
35769
35770 s = Fprevious_single_property_change
35771 (make_fixnum (pos + 1), Qmouse_face, object, Qnil);
35772 e = Fnext_single_property_change
35773 (position, Qmouse_face, object, Qnil);
35774 if (NILP (s))
35775 s = make_fixnum (0);
35776 if (NILP (e))
35777 e = make_fixnum (SCHARS (object));
35778 mouse_face_from_string_pos (w, hlinfo, object,
35779 XFIXNUM (s), XFIXNUM (e));
35780 hlinfo->mouse_face_past_end = false;
35781 hlinfo->mouse_face_window = window;
35782 hlinfo->mouse_face_face_id
35783 = face_at_string_position (w, object, pos, 0, &ignore,
35784 glyph->face_id, true, 0);
35785 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
35786 cursor = No_Cursor;
35787 }
35788 else
35789 {
35790
35791
35792 Lisp_Object buffer UNINIT;
35793 Lisp_Object disp_string UNINIT;
35794
35795 if (STRINGP (object))
35796 {
35797
35798
35799 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
35800 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35801 pos = string_buffer_position (object, start);
35802 if (pos > 0)
35803 {
35804 mouse_face = get_char_property_and_overlay
35805 (make_fixnum (pos), Qmouse_face, w->contents, &overlay);
35806 buffer = w->contents;
35807 disp_string = object;
35808 }
35809 }
35810 else
35811 {
35812 buffer = object;
35813 disp_string = Qnil;
35814 }
35815
35816 if (!NILP (mouse_face))
35817 {
35818 Lisp_Object before, after;
35819 Lisp_Object before_string, after_string;
35820
35821
35822
35823
35824
35825
35826
35827
35828
35829
35830 Lisp_Object lim1
35831 = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
35832 ? Fmarker_position (w->start)
35833 : Qnil;
35834 Lisp_Object lim2
35835 = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
35836 ? make_fixnum (BUF_Z (XBUFFER (buffer))
35837 - w->window_end_pos)
35838 : Qnil;
35839
35840 if (NILP (overlay))
35841 {
35842
35843 before = Fprevious_single_property_change
35844 (make_fixnum (pos + 1), Qmouse_face, buffer, lim1);
35845 after = Fnext_single_property_change
35846 (make_fixnum (pos), Qmouse_face, buffer, lim2);
35847 before_string = after_string = Qnil;
35848 }
35849 else
35850 {
35851
35852 before = Foverlay_start (overlay);
35853 after = Foverlay_end (overlay);
35854 before_string = Foverlay_get (overlay, Qbefore_string);
35855 after_string = Foverlay_get (overlay, Qafter_string);
35856
35857 if (!STRINGP (before_string)) before_string = Qnil;
35858 if (!STRINGP (after_string)) after_string = Qnil;
35859 }
35860
35861 mouse_face_from_buffer_pos (window, hlinfo, pos,
35862 NILP (before)
35863 ? 1
35864 : XFIXNAT (before),
35865 NILP (after)
35866 ? BUF_Z (XBUFFER (buffer))
35867 : XFIXNAT (after),
35868 before_string, after_string,
35869 disp_string);
35870 cursor = No_Cursor;
35871 }
35872 }
35873 }
35874
35875 check_help_echo:
35876
35877
35878 if (NILP (help_echo_string)) {
35879 Lisp_Object help, overlay;
35880
35881
35882 help = overlay = Qnil;
35883 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
35884 {
35885 overlay = overlay_vec[i];
35886 help = Foverlay_get (overlay, Qhelp_echo);
35887 }
35888
35889 if (!NILP (help))
35890 {
35891 help_echo_string = help;
35892 help_echo_window = window;
35893 help_echo_object = overlay;
35894 help_echo_pos = pos;
35895 }
35896 else
35897 {
35898 Lisp_Object obj = glyph->object;
35899 ptrdiff_t charpos = glyph->charpos;
35900
35901
35902 if (STRINGP (obj)
35903 && charpos >= 0
35904 && charpos < SCHARS (obj))
35905 {
35906 help = Fget_text_property (make_fixnum (charpos),
35907 Qhelp_echo, obj);
35908 if (NILP (help))
35909 {
35910
35911
35912 struct glyph_row *r
35913 = MATRIX_ROW (w->current_matrix, vpos);
35914 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35915 ptrdiff_t p = string_buffer_position (obj, start);
35916 if (p > 0)
35917 {
35918 help = Fget_char_property (make_fixnum (p),
35919 Qhelp_echo, w->contents);
35920 if (!NILP (help))
35921 {
35922 charpos = p;
35923 obj = w->contents;
35924 }
35925 }
35926 }
35927 }
35928 else if (BUFFERP (obj)
35929 && charpos >= BEGV
35930 && charpos < ZV)
35931 help = Fget_text_property (make_fixnum (charpos), Qhelp_echo,
35932 obj);
35933
35934 if (!NILP (help))
35935 {
35936 help_echo_string = help;
35937 help_echo_window = window;
35938 help_echo_object = obj;
35939 help_echo_pos = charpos;
35940 }
35941 }
35942 }
35943
35944 #ifdef HAVE_WINDOW_SYSTEM
35945
35946 if (FRAME_WINDOW_P (f) && NILP (pointer))
35947 {
35948
35949 for (i = noverlays - 1; i >= 0 && NILP (pointer); --i)
35950 pointer = Foverlay_get (overlay_vec[i], Qpointer);
35951
35952 if (NILP (pointer))
35953 {
35954 Lisp_Object obj = glyph->object;
35955 ptrdiff_t charpos = glyph->charpos;
35956
35957
35958 if (STRINGP (obj)
35959 && charpos >= 0
35960 && charpos < SCHARS (obj))
35961 {
35962 pointer = Fget_text_property (make_fixnum (charpos),
35963 Qpointer, obj);
35964 if (NILP (pointer))
35965 {
35966
35967
35968 struct glyph_row *r
35969 = MATRIX_ROW (w->current_matrix, vpos);
35970 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35971 ptrdiff_t p = string_buffer_position (obj, start);
35972 if (p > 0)
35973 pointer = Fget_char_property (make_fixnum (p),
35974 Qpointer, w->contents);
35975 }
35976 }
35977 else if (BUFFERP (obj)
35978 && charpos >= BEGV
35979 && charpos < ZV)
35980 pointer = Fget_text_property (make_fixnum (charpos),
35981 Qpointer, obj);
35982 }
35983 }
35984 #endif
35985
35986 BEGV = obegv;
35987 ZV = ozv;
35988 current_buffer = obuf;
35989 SAFE_FREE ();
35990 }
35991
35992 set_cursor:
35993 define_frame_cursor1 (f, cursor, pointer);
35994 }
35995
35996
35997
35998
35999
36000
36001
36002 void
36003 gui_clear_window_mouse_face (struct window *w)
36004 {
36005 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
36006 Lisp_Object window;
36007
36008 block_input ();
36009 XSETWINDOW (window, w);
36010 if (EQ (window, hlinfo->mouse_face_window))
36011 clear_mouse_face (hlinfo);
36012 unblock_input ();
36013 }
36014
36015
36016
36017
36018
36019
36020 void
36021 cancel_mouse_face (struct frame *f)
36022 {
36023 Lisp_Object window;
36024 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
36025
36026 window = hlinfo->mouse_face_window;
36027 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
36028 reset_mouse_highlight (hlinfo);
36029 }
36030
36031
36032
36033
36034
36035
36036
36037 #ifdef HAVE_WINDOW_SYSTEM
36038
36039
36040
36041
36042 static void
36043 expose_area (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r,
36044 enum glyph_row_area area)
36045 {
36046 struct glyph *first = row->glyphs[area];
36047 struct glyph *end = row->glyphs[area] + row->used[area];
36048 struct glyph *last;
36049 int first_x, start_x, x;
36050
36051 if (area == TEXT_AREA && row->fill_line_p)
36052
36053 draw_glyphs (w, row->x, row, area,
36054 0, row->used[area],
36055 DRAW_NORMAL_TEXT, 0);
36056 else
36057 {
36058
36059
36060
36061 start_x = window_box_left_offset (w, area);
36062 x = start_x;
36063 if (area == TEXT_AREA)
36064 x += row->x;
36065
36066
36067 while (first < end
36068 && x + first->pixel_width < r->x)
36069 {
36070 x += first->pixel_width;
36071 ++first;
36072 }
36073
36074
36075 last = first;
36076 first_x = x;
36077
36078
36079
36080 int r_end = r->x + r->width;
36081 while (last < end && x < r_end)
36082 {
36083 x += last->pixel_width;
36084 ++last;
36085 }
36086
36087
36088 if (last > first)
36089 draw_glyphs (w, first_x - start_x, row, area,
36090 first - row->glyphs[area], last - row->glyphs[area],
36091 DRAW_NORMAL_TEXT, 0);
36092 }
36093 }
36094
36095
36096
36097
36098
36099
36100 static bool
36101 expose_line (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r)
36102 {
36103 eassert (row->enabled_p);
36104
36105 if (row->mode_line_p || w->pseudo_window_p)
36106 draw_glyphs (w, 0, row, TEXT_AREA,
36107 0, row->used[TEXT_AREA],
36108 DRAW_NORMAL_TEXT, 0);
36109 else
36110 {
36111 if (row->used[LEFT_MARGIN_AREA])
36112 expose_area (w, row, r, LEFT_MARGIN_AREA);
36113 if (row->used[TEXT_AREA])
36114 expose_area (w, row, r, TEXT_AREA);
36115 if (row->used[RIGHT_MARGIN_AREA])
36116 expose_area (w, row, r, RIGHT_MARGIN_AREA);
36117 draw_row_fringe_bitmaps (w, row);
36118 }
36119
36120 return row->mouse_face_p;
36121 }
36122
36123
36124
36125
36126
36127
36128
36129
36130
36131
36132 static void
36133 expose_overlaps (struct window *w,
36134 struct glyph_row *first_overlapping_row,
36135 struct glyph_row *last_overlapping_row,
36136 const Emacs_Rectangle *r)
36137 {
36138 struct glyph_row *row;
36139
36140 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
36141 if (row->overlapping_p)
36142 {
36143 eassert (row->enabled_p && !row->mode_line_p);
36144
36145 row->clip = r;
36146 if (row->used[LEFT_MARGIN_AREA])
36147 gui_fix_overlapping_area (w, row, LEFT_MARGIN_AREA, OVERLAPS_BOTH);
36148
36149 if (row->used[TEXT_AREA])
36150 gui_fix_overlapping_area (w, row, TEXT_AREA, OVERLAPS_BOTH);
36151
36152 if (row->used[RIGHT_MARGIN_AREA])
36153 gui_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA, OVERLAPS_BOTH);
36154 row->clip = NULL;
36155 }
36156 }
36157
36158
36159
36160
36161 static bool
36162 phys_cursor_in_rect_p (struct window *w, const Emacs_Rectangle *r)
36163 {
36164 Emacs_Rectangle cr, result;
36165 struct glyph *cursor_glyph;
36166 struct glyph_row *row;
36167
36168 if (w->phys_cursor.vpos >= 0
36169 && w->phys_cursor.vpos < w->current_matrix->nrows
36170 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
36171 row->enabled_p)
36172 && row->cursor_in_fringe_p)
36173 {
36174
36175 cr.x = window_box_right_offset (w,
36176 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
36177 ? RIGHT_MARGIN_AREA
36178 : TEXT_AREA));
36179 cr.y = row->y;
36180 cr.width = WINDOW_RIGHT_FRINGE_WIDTH (w);
36181 cr.height = row->height;
36182 return gui_intersect_rectangles (&cr, r, &result);
36183 }
36184
36185 cursor_glyph = get_phys_cursor_glyph (w);
36186 if (cursor_glyph)
36187 {
36188
36189
36190 cr.x = window_box_left_offset (w, TEXT_AREA) + w->phys_cursor.x;
36191 cr.y = w->phys_cursor.y;
36192 cr.width = cursor_glyph->pixel_width;
36193 cr.height = w->phys_cursor_height;
36194
36195
36196 return gui_intersect_rectangles (&cr, r, &result);
36197 }
36198
36199 return false;
36200 }
36201
36202
36203
36204
36205
36206
36207 void
36208 gui_draw_vertical_border (struct window *w)
36209 {
36210 struct frame *f = XFRAME (WINDOW_FRAME (w));
36211
36212
36213
36214
36215
36216
36217
36218
36219
36220 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f) || FRAME_RIGHT_DIVIDER_WIDTH (f))
36221 return;
36222
36223
36224
36225
36226 if (!WINDOW_RIGHTMOST_P (w)
36227 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
36228 {
36229 int x0, x1, y0, y1;
36230
36231 window_box_edges (w, &x0, &y0, &x1, &y1);
36232 y1 -= 1;
36233
36234 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
36235 x1 -= 1;
36236
36237 FRAME_RIF (f)->draw_vertical_window_border (w, x1, y0, y1);
36238 }
36239
36240 if (!WINDOW_LEFTMOST_P (w)
36241 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
36242 {
36243 int x0, x1, y0, y1;
36244
36245 window_box_edges (w, &x0, &y0, &x1, &y1);
36246 y1 -= 1;
36247
36248 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
36249 x0 -= 1;
36250
36251 FRAME_RIF (f)->draw_vertical_window_border (w, x0, y0, y1);
36252 }
36253 }
36254
36255
36256
36257
36258 void
36259 gui_draw_right_divider (struct window *w)
36260 {
36261 struct frame *f = WINDOW_XFRAME (w);
36262
36263 if (w->mini || w->pseudo_window_p)
36264 return;
36265 else if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
36266 {
36267 int x0 = WINDOW_RIGHT_EDGE_X (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
36268 int x1 = WINDOW_RIGHT_EDGE_X (w);
36269 int y0 = WINDOW_TOP_EDGE_Y (w);
36270 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
36271
36272
36273
36274 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w)
36275 && !NILP (w->parent)
36276 && WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (w->parent))
36277 && !NILP (w->next))
36278 y1 -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
36279
36280 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
36281 }
36282 }
36283
36284 static void
36285 gui_draw_bottom_divider (struct window *w)
36286 {
36287 struct frame *f = XFRAME (WINDOW_FRAME (w));
36288
36289 if (w->mini || w->pseudo_window_p)
36290 return;
36291 else if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
36292 {
36293 int x0 = WINDOW_LEFT_EDGE_X (w);
36294 int x1 = WINDOW_RIGHT_EDGE_X (w);
36295 int y0 = WINDOW_BOTTOM_EDGE_Y (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
36296 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
36297 struct window *p = !NILP (w->parent) ? XWINDOW (w->parent) : NULL;
36298
36299
36300
36301 if (WINDOW_RIGHT_DIVIDER_WIDTH (w)
36302 && p
36303 && ((WINDOW_VERTICAL_COMBINATION_P (p)
36304 && !NILP (w->next))
36305 || (WINDOW_HORIZONTAL_COMBINATION_P (p)
36306 && NILP (w->next)
36307 && !NILP (p->parent)
36308 && WINDOW_VERTICAL_COMBINATION_P (XWINDOW (p->parent))
36309 && !NILP (XWINDOW (p->parent)->next))))
36310 x1 -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
36311
36312 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
36313 }
36314 }
36315
36316
36317
36318
36319
36320
36321 static bool
36322 expose_window (struct window *w, const Emacs_Rectangle *fr)
36323 {
36324 struct frame *f = XFRAME (w->frame);
36325 Emacs_Rectangle wr, r;
36326 bool mouse_face_overwritten_p = false;
36327
36328
36329
36330
36331
36332 if (w->current_matrix == NULL)
36333 return false;
36334
36335
36336
36337
36338 if (w->must_be_updated_p)
36339 {
36340 SET_FRAME_GARBAGED (f);
36341 return false;
36342 }
36343
36344
36345 wr.x = WINDOW_LEFT_EDGE_X (w);
36346 wr.y = WINDOW_TOP_EDGE_Y (w);
36347 wr.width = WINDOW_PIXEL_WIDTH (w);
36348 wr.height = WINDOW_PIXEL_HEIGHT (w);
36349
36350 if (gui_intersect_rectangles (fr, &wr, &r))
36351 {
36352 int yb = window_text_bottom_y (w);
36353 struct glyph_row *row;
36354 struct glyph_row *first_overlapping_row, *last_overlapping_row;
36355
36356 redisplay_trace ("expose_window (%d, %d, %u, %u)\n",
36357 r.x, r.y, r.width, r.height);
36358
36359
36360 r.x -= WINDOW_LEFT_EDGE_X (w);
36361 r.y -= WINDOW_TOP_EDGE_Y (w);
36362
36363
36364 bool cursor_cleared_p = (!w->pseudo_window_p
36365 && phys_cursor_in_rect_p (w, &r));
36366 if (cursor_cleared_p)
36367 gui_clear_cursor (w);
36368
36369
36370
36371
36372
36373
36374 bool phys_cursor_on_p = w->phys_cursor_on_p;
36375
36376
36377
36378
36379 int r_bottom = r.y + r.height;
36380
36381
36382
36383
36384
36385 bool buffer_changed = false;
36386 struct buffer *oldbuf = current_buffer;
36387 if (!w->pseudo_window_p)
36388 {
36389 set_buffer_internal_1 (XBUFFER (w->contents));
36390 buffer_changed = true;
36391 }
36392
36393
36394 first_overlapping_row = last_overlapping_row = NULL;
36395 for (row = w->current_matrix->rows;
36396 row->enabled_p;
36397 ++row)
36398 {
36399 int y0 = row->y;
36400 int y1 = MATRIX_ROW_BOTTOM_Y (row);
36401
36402 if ((y0 >= r.y && y0 < r_bottom)
36403 || (y1 > r.y && y1 < r_bottom)
36404 || (r.y >= y0 && r.y < y1)
36405 || (r_bottom > y0 && r_bottom < y1))
36406 {
36407
36408
36409 if (row->overlapping_p && !row->mode_line_p)
36410 {
36411 if (first_overlapping_row == NULL)
36412 first_overlapping_row = row;
36413 last_overlapping_row = row;
36414 }
36415
36416 row->clip = fr;
36417 if (expose_line (w, row, &r))
36418 mouse_face_overwritten_p = true;
36419 row->clip = NULL;
36420 }
36421 else if (row->overlapping_p)
36422 {
36423
36424 if (y0 < r.y
36425 ? y0 + row->phys_height > r.y
36426 : y0 + row->ascent - row->phys_ascent < r.y +r.height)
36427 {
36428 if (first_overlapping_row == NULL)
36429 first_overlapping_row = row;
36430 last_overlapping_row = row;
36431 }
36432 }
36433
36434 if (y1 >= yb)
36435 break;
36436 }
36437
36438 if (buffer_changed)
36439 set_buffer_internal_1 (oldbuf);
36440
36441
36442 if (window_wants_mode_line (w)
36443 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
36444 row->enabled_p)
36445 && row->y < r_bottom)
36446 {
36447 if (expose_line (w, row, &r))
36448 mouse_face_overwritten_p = true;
36449 }
36450
36451 if (!w->pseudo_window_p)
36452 {
36453
36454 if (first_overlapping_row)
36455 expose_overlaps (w, first_overlapping_row, last_overlapping_row,
36456 fr);
36457
36458
36459 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
36460 gui_draw_right_divider (w);
36461 else
36462 gui_draw_vertical_border (w);
36463
36464 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
36465 gui_draw_bottom_divider (w);
36466
36467
36468 if (cursor_cleared_p
36469 || (phys_cursor_on_p && !w->phys_cursor_on_p))
36470 update_window_cursor (w, true);
36471 }
36472 }
36473
36474 return mouse_face_overwritten_p;
36475 }
36476
36477
36478
36479
36480
36481
36482
36483 static bool
36484 expose_window_tree (struct window *w, const Emacs_Rectangle *r)
36485 {
36486 struct frame *f = XFRAME (w->frame);
36487 bool mouse_face_overwritten_p = false;
36488
36489 while (w && !FRAME_GARBAGED_P (f))
36490 {
36491 mouse_face_overwritten_p
36492 |= (WINDOWP (w->contents)
36493 ? expose_window_tree (XWINDOW (w->contents), r)
36494 : expose_window (w, r));
36495
36496 w = NILP (w->next) ? NULL : XWINDOW (w->next);
36497 }
36498
36499 return mouse_face_overwritten_p;
36500 }
36501
36502
36503
36504
36505
36506
36507
36508
36509 void
36510 expose_frame (struct frame *f, int x, int y, int w, int h)
36511 {
36512 Emacs_Rectangle r;
36513 bool mouse_face_overwritten_p = false;
36514
36515 if (FRAME_GARBAGED_P (f))
36516 {
36517 redisplay_trace ("expose_frame garbaged\n");
36518 return;
36519 }
36520
36521
36522
36523
36524 if (FRAME_FACE_CACHE (f) == NULL
36525 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
36526 {
36527 redisplay_trace ("expose_frame no faces\n");
36528 return;
36529 }
36530
36531 if (w == 0 || h == 0)
36532 {
36533 r.x = r.y = 0;
36534 r.width = FRAME_TEXT_WIDTH (f);
36535 r.height = FRAME_TEXT_HEIGHT (f);
36536 }
36537 else
36538 {
36539 r.x = x;
36540 r.y = y;
36541 r.width = w;
36542 r.height = h;
36543 }
36544
36545 redisplay_trace ("expose_frame (%d, %d, %u, %u)\n",
36546 r.x, r.y, r.width, r.height);
36547 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
36548
36549 if (WINDOWP (f->tab_bar_window))
36550 mouse_face_overwritten_p
36551 |= expose_window (XWINDOW (f->tab_bar_window), &r);
36552
36553 #ifndef HAVE_EXT_TOOL_BAR
36554 if (WINDOWP (f->tool_bar_window))
36555 mouse_face_overwritten_p
36556 |= expose_window (XWINDOW (f->tool_bar_window), &r);
36557 #endif
36558
36559 #if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
36560 if (WINDOWP (f->menu_bar_window))
36561 mouse_face_overwritten_p
36562 |= expose_window (XWINDOW (f->menu_bar_window), &r);
36563 #endif
36564
36565
36566
36567
36568
36569
36570
36571
36572
36573
36574
36575
36576
36577
36578 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
36579 {
36580 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
36581 if (f == hlinfo->mouse_face_mouse_frame)
36582 {
36583 int mouse_x = hlinfo->mouse_face_mouse_x;
36584 int mouse_y = hlinfo->mouse_face_mouse_y;
36585 clear_mouse_face (hlinfo);
36586 note_mouse_highlight (f, mouse_x, mouse_y);
36587 }
36588 }
36589 }
36590
36591
36592
36593
36594
36595
36596
36597 bool
36598 gui_intersect_rectangles (const Emacs_Rectangle *r1, const Emacs_Rectangle *r2,
36599 Emacs_Rectangle *result)
36600 {
36601 const Emacs_Rectangle *left, *right;
36602 const Emacs_Rectangle *upper, *lower;
36603 bool intersection_p = false;
36604
36605
36606 if (r1->x < r2->x)
36607 left = r1, right = r2;
36608 else
36609 left = r2, right = r1;
36610
36611
36612
36613 if (right->x <= left->x + left->width)
36614 {
36615 result->x = right->x;
36616
36617
36618
36619 result->width = (min (left->x + left->width, right->x + right->width)
36620 - result->x);
36621
36622
36623 if (r1->y < r2->y)
36624 upper = r1, lower = r2;
36625 else
36626 upper = r2, lower = r1;
36627
36628
36629
36630 if (lower->y <= upper->y + upper->height)
36631 {
36632 result->y = lower->y;
36633
36634
36635
36636 result->height = (min (lower->y + lower->height,
36637 upper->y + upper->height)
36638 - result->y);
36639 intersection_p = true;
36640 }
36641 }
36642
36643 return intersection_p;
36644 }
36645
36646
36647
36648
36649
36650
36651 void
36652 gui_union_rectangles (const Emacs_Rectangle *a, const Emacs_Rectangle *b,
36653 Emacs_Rectangle *result)
36654 {
36655 struct gui_box a_box, b_box, result_box;
36656
36657
36658
36659 if (!a->width || !a->height)
36660 {
36661 *result = *b;
36662 return;
36663 }
36664 else if (!b->width || !b->height)
36665 {
36666 *result = *a;
36667 return;
36668 }
36669
36670
36671 a_box.x1 = a->x;
36672 a_box.y1 = a->y;
36673 a_box.x2 = a->x + a->width;
36674 a_box.y2 = a->y + a->height;
36675
36676 b_box.x1 = b->x;
36677 b_box.y1 = b->y;
36678 b_box.x2 = b->x + b->width;
36679 b_box.y2 = b->y + b->height;
36680
36681
36682 result_box.x1 = min (a_box.x1, b_box.x1);
36683 result_box.y1 = min (a_box.y1, b_box.y1);
36684 result_box.x2 = max (a_box.x2, b_box.x2);
36685 result_box.y2 = max (a_box.y2, b_box.y2);
36686
36687
36688
36689 result->x = result_box.x1;
36690 result->y = result_box.y1;
36691 result->width = result_box.x2 - result_box.x1;
36692 result->height = result_box.y2 - result_box.y1;
36693 }
36694
36695 #endif
36696
36697
36698
36699
36700
36701
36702 void
36703 syms_of_xdisp (void)
36704 {
36705 Vwith_echo_area_save_vector = Qnil;
36706 staticpro (&Vwith_echo_area_save_vector);
36707
36708 Vmessage_stack = Qnil;
36709 staticpro (&Vmessage_stack);
36710
36711
36712 DEFSYM (Qinhibit_redisplay, "inhibit-redisplay");
36713
36714 DEFSYM (Qredisplay_internal_xC_functionx, "redisplay_internal (C function)");
36715
36716 DEFVAR_BOOL ("scroll-minibuffer-conservatively",
36717 scroll_minibuffer_conservatively,
36718 doc:
36719
36720 );
36721 scroll_minibuffer_conservatively = true;
36722
36723 DEFVAR_BOOL ("inhibit-message", inhibit_message,
36724 doc:
36725
36726
36727
36728
36729
36730 );
36731 inhibit_message = false;
36732
36733 message_dolog_marker1 = Fmake_marker ();
36734 staticpro (&message_dolog_marker1);
36735 message_dolog_marker2 = Fmake_marker ();
36736 staticpro (&message_dolog_marker2);
36737 message_dolog_marker3 = Fmake_marker ();
36738 staticpro (&message_dolog_marker3);
36739
36740 defsubr (&Sset_buffer_redisplay);
36741 #ifdef GLYPH_DEBUG
36742 defsubr (&Sdump_frame_glyph_matrix);
36743 defsubr (&Sdump_glyph_matrix);
36744 defsubr (&Sdump_glyph_row);
36745 defsubr (&Sdump_tab_bar_row);
36746 defsubr (&Sdump_tool_bar_row);
36747 defsubr (&Strace_redisplay);
36748 defsubr (&Strace_to_stderr);
36749 #endif
36750 #ifdef HAVE_WINDOW_SYSTEM
36751 defsubr (&Stab_bar_height);
36752 defsubr (&Stool_bar_height);
36753 defsubr (&Slookup_image_map);
36754 #endif
36755 defsubr (&Sline_pixel_height);
36756 defsubr (&Sformat_mode_line);
36757 defsubr (&Sinvisible_p);
36758 defsubr (&Scurrent_bidi_paragraph_direction);
36759 defsubr (&Swindow_text_pixel_size);
36760 defsubr (&Sbuffer_text_pixel_size);
36761 defsubr (&Smove_point_visually);
36762 defsubr (&Sbidi_find_overridden_directionality);
36763 defsubr (&Sdisplay__line_is_continued_p);
36764 defsubr (&Sget_display_property);
36765 defsubr (&Slong_line_optimizations_p);
36766
36767 DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook");
36768 DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map");
36769 DEFSYM (Qoverriding_local_map, "overriding-local-map");
36770 DEFSYM (Qwindow_scroll_functions, "window-scroll-functions");
36771 DEFSYM (Qinhibit_point_motion_hooks, "inhibit-point-motion-hooks");
36772 DEFSYM (Qeval, "eval");
36773 DEFSYM (QCdata, ":data");
36774
36775
36776 DEFSYM (Qdisplay, "display");
36777 DEFSYM (Qspace_width, "space-width");
36778 DEFSYM (Qraise, "raise");
36779 DEFSYM (Qslice, "slice");
36780 DEFSYM (Qspace, "space");
36781 DEFSYM (Qmargin, "margin");
36782 DEFSYM (Qpointer, "pointer");
36783 DEFSYM (Qleft_margin, "left-margin");
36784 DEFSYM (Qright_margin, "right-margin");
36785 DEFSYM (Qcenter, "center");
36786 DEFSYM (Qline_height, "line-height");
36787 DEFSYM (QCalign_to, ":align-to");
36788 DEFSYM (QCrelative_width, ":relative-width");
36789 DEFSYM (QCrelative_height, ":relative-height");
36790 DEFSYM (QCeval, ":eval");
36791 DEFSYM (QCpropertize, ":propertize");
36792 DEFSYM (QCfile, ":file");
36793 DEFSYM (Qfontified, "fontified");
36794 DEFSYM (Qfontification_functions, "fontification-functions");
36795 DEFSYM (Qlong_line_optimizations_in_fontification_functions,
36796 "long-line-optimizations-in-fontification-functions");
36797
36798
36799
36800 DEFSYM (Qdisable_eval, "disable-eval");
36801
36802
36803 DEFSYM (Qtrailing_whitespace, "trailing-whitespace");
36804
36805
36806 DEFSYM (Qline_number, "line-number");
36807 DEFSYM (Qline_number_current_line, "line-number-current-line");
36808 DEFSYM (Qline_number_major_tick, "line-number-major-tick");
36809 DEFSYM (Qline_number_minor_tick, "line-number-minor-tick");
36810
36811 DEFSYM (Qdisplay_line_numbers_disable, "display-line-numbers-disable");
36812
36813
36814 DEFSYM (Qfill_column_indicator, "fill-column-indicator");
36815
36816
36817 DEFSYM (Qescape_glyph, "escape-glyph");
36818
36819
36820
36821 DEFSYM (Qnobreak_space, "nobreak-space");
36822 DEFSYM (Qnobreak_hyphen, "nobreak-hyphen");
36823
36824
36825
36826 DEFSYM (Qimage, "image");
36827
36828
36829 DEFSYM (Qtext, "text");
36830 DEFSYM (Qboth, "both");
36831 DEFSYM (Qboth_horiz, "both-horiz");
36832 DEFSYM (Qtext_image_horiz, "text-image-horiz");
36833
36834
36835 DEFSYM (QCmap, ":map");
36836 DEFSYM (QCpointer, ":pointer");
36837 DEFSYM (Qrect, "rect");
36838 DEFSYM (Qcircle, "circle");
36839 DEFSYM (Qpoly, "poly");
36840
36841 DEFSYM (Qinhibit_menubar_update, "inhibit-menubar-update");
36842
36843 DEFSYM (Qgrow_only, "grow-only");
36844 DEFSYM (Qinhibit_eval_during_redisplay, "inhibit-eval-during-redisplay");
36845 DEFSYM (Qposition, "position");
36846 DEFSYM (Qbuffer_position, "buffer-position");
36847 DEFSYM (Qobject, "object");
36848
36849
36850 DEFSYM (Qbar, "bar");
36851 DEFSYM (Qhbar, "hbar");
36852 DEFSYM (Qbox, "box");
36853 DEFSYM (Qhollow, "hollow");
36854
36855
36856 DEFSYM (Qhand, "hand");
36857 DEFSYM (Qarrow, "arrow");
36858
36859
36860 DEFSYM (Qdragging, "dragging");
36861 DEFSYM (Qdropping, "dropping");
36862 DEFSYM (Qdrag_source, "drag-source");
36863
36864 DEFSYM (Qdrag_with_mode_line, "drag-with-mode-line");
36865 DEFSYM (Qdrag_with_header_line, "drag-with-header-line");
36866 DEFSYM (Qdrag_with_tab_line, "drag-with-tab-line");
36867
36868 DEFSYM (Qinhibit_free_realized_faces, "inhibit-free-realized-faces");
36869
36870 list_of_error = list1 (Qerror);
36871 staticpro (&list_of_error);
36872
36873
36874
36875
36876
36877 DEFSYM (Qlast_arrow_position, "last-arrow-position");
36878 DEFSYM (Qlast_arrow_string, "last-arrow-string");
36879
36880
36881
36882 DEFSYM (Qoverlay_arrow_string, "overlay-arrow-string");
36883 DEFSYM (Qoverlay_arrow_bitmap, "overlay-arrow-bitmap");
36884
36885 echo_buffer[0] = echo_buffer[1] = Qnil;
36886 staticpro (&echo_buffer[0]);
36887 staticpro (&echo_buffer[1]);
36888
36889 echo_area_buffer[0] = echo_area_buffer[1] = Qnil;
36890 staticpro (&echo_area_buffer[0]);
36891 staticpro (&echo_area_buffer[1]);
36892
36893 DEFVAR_LISP ("messages-buffer-name", Vmessages_buffer_name,
36894 doc:
36895
36896
36897
36898 );
36899 Vmessages_buffer_name = build_string ("*Messages*");
36900
36901 mode_line_proptrans_alist = Qnil;
36902 staticpro (&mode_line_proptrans_alist);
36903 mode_line_string_list = Qnil;
36904 staticpro (&mode_line_string_list);
36905 mode_line_string_face = Qnil;
36906 staticpro (&mode_line_string_face);
36907 mode_line_string_face_prop = Qnil;
36908 staticpro (&mode_line_string_face_prop);
36909 Vmode_line_unwind_vector = Qnil;
36910 staticpro (&Vmode_line_unwind_vector);
36911
36912 DEFSYM (Qmode_line_default_help_echo, "mode-line-default-help-echo");
36913
36914 help_echo_string = Qnil;
36915 staticpro (&help_echo_string);
36916 help_echo_object = Qnil;
36917 staticpro (&help_echo_object);
36918 help_echo_window = Qnil;
36919 staticpro (&help_echo_window);
36920 previous_help_echo_string = Qnil;
36921 staticpro (&previous_help_echo_string);
36922 help_echo_pos = -1;
36923
36924 DEFSYM (Qright_to_left, "right-to-left");
36925 DEFSYM (Qleft_to_right, "left-to-right");
36926 defsubr (&Sbidi_resolved_levels);
36927
36928 #ifdef HAVE_WINDOW_SYSTEM
36929 DEFVAR_BOOL ("x-stretch-cursor", x_stretch_cursor_p,
36930 doc:
36931
36932 );
36933 x_stretch_cursor_p = 0;
36934 #endif
36935
36936 DEFVAR_LISP ("show-trailing-whitespace", Vshow_trailing_whitespace,
36937 doc:
36938 );
36939 Vshow_trailing_whitespace = Qnil;
36940
36941 DEFVAR_LISP ("mode-line-compact", Vmode_line_compact,
36942 doc:
36943
36944
36945 );
36946 Vmode_line_compact = Qnil;
36947 DEFSYM (Qlong, "long");
36948
36949 DEFVAR_LISP ("nobreak-char-display", Vnobreak_char_display,
36950 doc:
36951
36952
36953
36954
36955
36956
36957
36958
36959
36960
36961
36962 );
36963 Vnobreak_char_display = Qt;
36964
36965 DEFVAR_BOOL ("nobreak-char-ascii-display", nobreak_char_ascii_display,
36966 doc:
36967
36968
36969
36970
36971
36972
36973
36974
36975
36976
36977
36978
36979
36980
36981
36982 );
36983 nobreak_char_ascii_display = false;
36984
36985 DEFVAR_LISP ("void-text-area-pointer", Vvoid_text_area_pointer,
36986 doc:
36987
36988
36989 );
36990 Vvoid_text_area_pointer = Qarrow;
36991
36992 DEFVAR_LISP ("inhibit-redisplay", Vinhibit_redisplay,
36993 doc:
36994 );
36995 Vinhibit_redisplay = Qnil;
36996
36997 DEFVAR_LISP ("global-mode-string", Vglobal_mode_string,
36998 doc: );
36999 Vglobal_mode_string = Qnil;
37000
37001 DEFVAR_LISP ("overlay-arrow-position", Voverlay_arrow_position,
37002 doc:
37003
37004 );
37005 Voverlay_arrow_position = Qnil;
37006
37007 DEFVAR_LISP ("overlay-arrow-string", Voverlay_arrow_string,
37008 doc:
37009 );
37010 Voverlay_arrow_string = build_pure_c_string ("=>");
37011
37012 DEFVAR_LISP ("overlay-arrow-variable-list", Voverlay_arrow_variable_list,
37013 doc:
37014
37015 );
37016 Voverlay_arrow_variable_list
37017 = list1 (intern_c_string ("overlay-arrow-position"));
37018
37019 DEFVAR_INT ("scroll-step", emacs_scroll_step,
37020 doc:
37021
37022
37023
37024 );
37025
37026 DEFVAR_INT ("scroll-conservatively", scroll_conservatively,
37027 doc:
37028
37029
37030
37031
37032
37033
37034
37035
37036
37037 );
37038 scroll_conservatively = 0;
37039
37040 DEFVAR_INT ("scroll-margin", scroll_margin,
37041 doc:
37042
37043 );
37044 scroll_margin = 0;
37045
37046 DEFVAR_LISP ("maximum-scroll-margin", Vmaximum_scroll_margin,
37047 doc:
37048
37049
37050
37051 );
37052 Vmaximum_scroll_margin = make_float (0.25);
37053
37054 DEFVAR_LISP ("display-pixels-per-inch", Vdisplay_pixels_per_inch,
37055 doc:
37056 );
37057 Vdisplay_pixels_per_inch = make_float (72.0);
37058
37059 #ifdef GLYPH_DEBUG
37060 DEFVAR_INT ("debug-end-pos", debug_end_pos, doc: );
37061 #endif
37062
37063 DEFVAR_LISP ("truncate-partial-width-windows",
37064 Vtruncate_partial_width_windows,
37065 doc:
37066
37067
37068
37069
37070
37071
37072
37073
37074
37075
37076
37077
37078
37079
37080
37081 );
37082 Vtruncate_partial_width_windows = make_fixnum (50);
37083
37084 DEFVAR_BOOL("word-wrap-by-category", word_wrap_by_category, doc:
37085
37086
37087
37088
37089
37090
37091
37092
37093
37094
37095
37096
37097
37098 );
37099 word_wrap_by_category = false;
37100
37101 DEFVAR_LISP ("line-number-display-limit", Vline_number_display_limit,
37102 doc:
37103
37104 );
37105 Vline_number_display_limit = Qnil;
37106
37107 DEFVAR_INT ("line-number-display-limit-width",
37108 line_number_display_limit_width,
37109 doc:
37110
37111 );
37112 line_number_display_limit_width = 200;
37113
37114 DEFVAR_BOOL ("highlight-nonselected-windows", highlight_nonselected_windows,
37115 doc:
37116
37117 );
37118 highlight_nonselected_windows = false;
37119
37120 DEFVAR_BOOL ("multiple-frames", multiple_frames,
37121 doc:
37122
37123
37124 );
37125
37126 DEFVAR_LISP ("frame-title-format", Vframe_title_format,
37127 doc:
37128
37129
37130
37131
37132 );
37133
37134 DEFVAR_LISP ("icon-title-format", Vicon_title_format,
37135 doc:
37136
37137
37138
37139
37140
37141 );
37142
37143
37144 Lisp_Object icon_title_name_format
37145 = pure_list (empty_unibyte_string,
37146 build_pure_c_string ("%b - GNU Emacs at "),
37147 intern_c_string ("system-name"));
37148 Vicon_title_format
37149 = Vframe_title_format
37150 = pure_list (intern_c_string ("multiple-frames"),
37151 build_pure_c_string ("%b"),
37152 icon_title_name_format);
37153
37154 DEFVAR_LISP ("message-log-max", Vmessage_log_max,
37155 doc:
37156
37157 );
37158 Vmessage_log_max = make_fixnum (1000);
37159
37160 DEFVAR_LISP ("window-scroll-functions", Vwindow_scroll_functions,
37161 doc:
37162
37163
37164
37165
37166
37167
37168
37169
37170
37171
37172
37173
37174
37175 );
37176 Vwindow_scroll_functions = Qnil;
37177
37178 DEFVAR_LISP ("mouse-autoselect-window", Vmouse_autoselect_window,
37179 doc:
37180
37181
37182
37183
37184
37185
37186
37187
37188
37189
37190
37191
37192
37193
37194
37195
37196
37197 );
37198 Vmouse_autoselect_window = Qnil;
37199
37200 DEFVAR_LISP ("auto-resize-tab-bars", Vauto_resize_tab_bars,
37201 doc:
37202
37203
37204
37205
37206 );
37207 Vauto_resize_tab_bars = Qt;
37208
37209 DEFVAR_BOOL ("auto-raise-tab-bar-buttons", auto_raise_tab_bar_buttons_p,
37210 doc: );
37211 auto_raise_tab_bar_buttons_p = true;
37212
37213 DEFVAR_LISP ("auto-resize-tool-bars", Vauto_resize_tool_bars,
37214 doc:
37215
37216
37217
37218
37219 );
37220 Vauto_resize_tool_bars = Qt;
37221
37222 DEFVAR_BOOL ("auto-raise-tool-bar-buttons", auto_raise_tool_bar_buttons_p,
37223 doc: );
37224 auto_raise_tool_bar_buttons_p = true;
37225
37226 DEFVAR_LISP ("make-cursor-line-fully-visible", Vmake_cursor_line_fully_visible,
37227 doc:
37228
37229
37230
37231
37232 );
37233 Vmake_cursor_line_fully_visible = Qt;
37234 DEFSYM (Qmake_cursor_line_fully_visible, "make-cursor-line-fully-visible");
37235
37236 DEFVAR_BOOL ("make-window-start-visible", make_window_start_visible,
37237 doc: );
37238 make_window_start_visible = false;
37239 DEFSYM (Qmake_window_start_visible, "make-window-start-visible");
37240 Fmake_variable_buffer_local (Qmake_window_start_visible);
37241
37242 DEFSYM (Qclose_tab, "close-tab");
37243 DEFVAR_LISP ("tab-bar-border", Vtab_bar_border,
37244 doc:
37245
37246
37247
37248 );
37249 Vtab_bar_border = Qinternal_border_width;
37250
37251 DEFVAR_LISP ("tab-bar-button-margin", Vtab_bar_button_margin,
37252 doc:
37253
37254
37255
37256 );
37257 Vtab_bar_button_margin = make_fixnum (DEFAULT_TAB_BAR_BUTTON_MARGIN);
37258
37259 DEFVAR_INT ("tab-bar-button-relief", tab_bar_button_relief,
37260 doc: );
37261 tab_bar_button_relief = DEFAULT_TAB_BAR_BUTTON_RELIEF;
37262
37263 DEFVAR_LISP ("tool-bar-border", Vtool_bar_border,
37264 doc:
37265
37266
37267
37268 );
37269 Vtool_bar_border = Qinternal_border_width;
37270
37271 DEFVAR_LISP ("tool-bar-button-margin", Vtool_bar_button_margin,
37272 doc:
37273
37274
37275
37276 );
37277 Vtool_bar_button_margin = make_fixnum (DEFAULT_TOOL_BAR_BUTTON_MARGIN);
37278
37279 DEFVAR_INT ("tool-bar-button-relief", tool_bar_button_relief,
37280 doc: );
37281 tool_bar_button_relief = DEFAULT_TOOL_BAR_BUTTON_RELIEF;
37282
37283 DEFVAR_LISP ("tool-bar-style", Vtool_bar_style,
37284 doc:
37285
37286
37287
37288
37289
37290
37291
37292
37293 );
37294 Vtool_bar_style = Qnil;
37295
37296 DEFVAR_INT ("tool-bar-max-label-size", tool_bar_max_label_size,
37297 doc:
37298
37299 );
37300 tool_bar_max_label_size = DEFAULT_TOOL_BAR_LABEL_SIZE;
37301
37302 DEFVAR_LISP ("fontification-functions", Vfontification_functions,
37303 doc:
37304
37305
37306
37307
37308
37309
37310
37311
37312 );
37313 Vfontification_functions = Qnil;
37314 Fmake_variable_buffer_local (Qfontification_functions);
37315
37316 DEFVAR_BOOL ("unibyte-display-via-language-environment",
37317 unibyte_display_via_language_environment,
37318 doc:
37319
37320
37321
37322
37323
37324
37325 );
37326 unibyte_display_via_language_environment = false;
37327
37328 DEFVAR_LISP ("max-mini-window-height", Vmax_mini_window_height,
37329 doc:
37330
37331
37332
37333 );
37334 Vmax_mini_window_height = make_float (0.25);
37335
37336 DEFVAR_LISP ("resize-mini-windows", Vresize_mini_windows,
37337 doc:
37338
37339
37340
37341
37342
37343
37344
37345
37346 );
37347
37348
37349
37350
37351
37352 Vresize_mini_windows = Qnil;
37353
37354 DEFVAR_LISP ("blink-cursor-alist", Vblink_cursor_alist,
37355 doc:
37356
37357
37358
37359
37360
37361
37362
37363 );
37364 Vblink_cursor_alist = Qnil;
37365
37366 DEFVAR_LISP ("auto-hscroll-mode", automatic_hscrolling,
37367 doc:
37368
37369
37370
37371 );
37372 automatic_hscrolling = Qt;
37373 DEFSYM (Qauto_hscroll_mode, "auto-hscroll-mode");
37374 DEFSYM (Qcurrent_line, "current-line");
37375
37376 DEFVAR_INT ("hscroll-margin", hscroll_margin,
37377 doc:
37378 );
37379 hscroll_margin = 5;
37380
37381 DEFVAR_LISP ("hscroll-step", Vhscroll_step,
37382 doc:
37383
37384
37385
37386
37387
37388
37389
37390
37391
37392
37393
37394
37395
37396 );
37397 Vhscroll_step = make_fixnum (0);
37398
37399 DEFVAR_BOOL ("message-truncate-lines", message_truncate_lines,
37400 doc:
37401 );
37402 message_truncate_lines = false;
37403
37404 DEFVAR_LISP ("menu-bar-update-hook", Vmenu_bar_update_hook,
37405 doc:
37406
37407
37408 );
37409 Vmenu_bar_update_hook = Qnil;
37410
37411 DEFVAR_LISP ("menu-updating-frame", Vmenu_updating_frame,
37412 doc:
37413 );
37414 Vmenu_updating_frame = Qnil;
37415
37416 DEFVAR_BOOL ("inhibit-menubar-update", inhibit_menubar_update,
37417 doc: );
37418 inhibit_menubar_update = false;
37419
37420 DEFVAR_LISP ("wrap-prefix", Vwrap_prefix,
37421 doc:
37422
37423
37424
37425
37426
37427
37428 );
37429 Vwrap_prefix = Qnil;
37430 DEFSYM (Qwrap_prefix, "wrap-prefix");
37431 Fmake_variable_buffer_local (Qwrap_prefix);
37432
37433 DEFVAR_LISP ("line-prefix", Vline_prefix,
37434 doc:
37435
37436
37437
37438
37439
37440
37441 );
37442 Vline_prefix = Qnil;
37443 DEFSYM (Qline_prefix, "line-prefix");
37444 Fmake_variable_buffer_local (Qline_prefix);
37445
37446 DEFVAR_LISP ("display-line-numbers", Vdisplay_line_numbers,
37447 doc:
37448
37449
37450
37451
37452
37453
37454
37455
37456
37457
37458
37459
37460
37461
37462
37463
37464
37465
37466
37467
37468
37469
37470 );
37471 Vdisplay_line_numbers = Qnil;
37472 DEFSYM (Qdisplay_line_numbers, "display-line-numbers");
37473 Fmake_variable_buffer_local (Qdisplay_line_numbers);
37474 DEFSYM (Qrelative, "relative");
37475 DEFSYM (Qvisual, "visual");
37476
37477 DEFVAR_LISP ("display-line-numbers-width", Vdisplay_line_numbers_width,
37478 doc:
37479
37480
37481
37482 );
37483 Vdisplay_line_numbers_width = Qnil;
37484 DEFSYM (Qdisplay_line_numbers_width, "display-line-numbers-width");
37485 Fmake_variable_buffer_local (Qdisplay_line_numbers_width);
37486
37487 DEFVAR_LISP ("display-line-numbers-current-absolute",
37488 Vdisplay_line_numbers_current_absolute,
37489 doc:
37490
37491 );
37492 Vdisplay_line_numbers_current_absolute = Qt;
37493
37494 DEFVAR_BOOL ("display-line-numbers-widen", display_line_numbers_widen,
37495 doc: );
37496 display_line_numbers_widen = false;
37497 DEFSYM (Qdisplay_line_numbers_widen, "display-line-numbers-widen");
37498 Fmake_variable_buffer_local (Qdisplay_line_numbers_widen);
37499
37500 DEFVAR_INT ("display-line-numbers-offset", display_line_numbers_offset,
37501 doc:
37502
37503
37504 );
37505 display_line_numbers_offset = 0;
37506 DEFSYM (Qdisplay_line_numbers_offset, "display-line-numbers-offset");
37507 Fmake_variable_buffer_local (Qdisplay_line_numbers_offset);
37508
37509 DEFVAR_BOOL ("display-fill-column-indicator", display_fill_column_indicator,
37510 doc:
37511
37512
37513 );
37514 display_fill_column_indicator = false;
37515 DEFSYM (Qdisplay_fill_column_indicator, "display-fill-column-indicator");
37516 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator);
37517
37518 DEFVAR_LISP ("display-fill-column-indicator-column", Vdisplay_fill_column_indicator_column,
37519 doc:
37520
37521
37522
37523 );
37524 Vdisplay_fill_column_indicator_column = Qt;
37525 DEFSYM (Qdisplay_fill_column_indicator_column, "display-fill-column-indicator-column");
37526 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_column);
37527
37528 DEFVAR_LISP ("display-fill-column-indicator-character", Vdisplay_fill_column_indicator_character,
37529 doc:
37530
37531
37532 );
37533 Vdisplay_fill_column_indicator_character = Qnil;
37534 DEFSYM (Qdisplay_fill_column_indicator_character, "display-fill-column-indicator-character");
37535 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_character);
37536
37537 DEFVAR_INT ("display-line-numbers-major-tick", display_line_numbers_major_tick,
37538 doc:
37539
37540
37541 );
37542 display_line_numbers_major_tick = 0;
37543
37544 DEFVAR_INT ("display-line-numbers-minor-tick", display_line_numbers_minor_tick,
37545 doc:
37546
37547
37548 );
37549 display_line_numbers_minor_tick = 0;
37550
37551 DEFVAR_BOOL ("inhibit-eval-during-redisplay", inhibit_eval_during_redisplay,
37552 doc: );
37553 inhibit_eval_during_redisplay = false;
37554
37555 DEFVAR_BOOL ("inhibit-free-realized-faces", inhibit_free_realized_faces,
37556 doc: );
37557 inhibit_free_realized_faces = false;
37558
37559 DEFVAR_BOOL ("inhibit-bidi-mirroring", inhibit_bidi_mirroring,
37560 doc:
37561
37562 );
37563 inhibit_bidi_mirroring = false;
37564
37565 DEFVAR_BOOL ("bidi-inhibit-bpa", bidi_inhibit_bpa,
37566 doc:
37567
37568
37569
37570 );
37571 bidi_inhibit_bpa = false;
37572
37573 #ifdef GLYPH_DEBUG
37574 DEFVAR_BOOL ("inhibit-try-window-id", inhibit_try_window_id,
37575 doc: );
37576 inhibit_try_window_id = false;
37577
37578 DEFVAR_BOOL ("inhibit-try-window-reusing", inhibit_try_window_reusing,
37579 doc: );
37580 inhibit_try_window_reusing = false;
37581
37582 DEFVAR_BOOL ("inhibit-try-cursor-movement", inhibit_try_cursor_movement,
37583 doc: );
37584 inhibit_try_cursor_movement = false;
37585 #endif
37586
37587 DEFVAR_INT ("overline-margin", overline_margin,
37588 doc:
37589
37590 );
37591 overline_margin = 2;
37592
37593 DEFVAR_INT ("underline-minimum-offset",
37594 underline_minimum_offset,
37595 doc:
37596
37597
37598
37599 );
37600 underline_minimum_offset = 1;
37601 DEFSYM (Qunderline_minimum_offset, "underline-minimum-offset");
37602
37603 DEFVAR_BOOL ("display-hourglass", display_hourglass_p,
37604 doc:
37605
37606 );
37607 display_hourglass_p = true;
37608
37609 DEFVAR_LISP ("hourglass-delay", Vhourglass_delay,
37610 doc: );
37611 Vhourglass_delay = make_fixnum (DEFAULT_HOURGLASS_DELAY);
37612
37613 #ifdef HAVE_WINDOW_SYSTEM
37614 hourglass_atimer = NULL;
37615 hourglass_shown_p = false;
37616 #endif
37617
37618
37619 DEFSYM (Qglyphless_char, "glyphless-char");
37620
37621
37622 DEFSYM (Qhex_code, "hex-code");
37623 DEFSYM (Qempty_box, "empty-box");
37624 DEFSYM (Qthin_space, "thin-space");
37625 DEFSYM (Qzero_width, "zero-width");
37626
37627 DEFVAR_LISP ("pre-redisplay-function", Vpre_redisplay_function,
37628 doc:
37629
37630
37631 );
37632 Vpre_redisplay_function = intern ("ignore");
37633
37634
37635 DEFSYM (Qglyphless_char_display, "glyphless-char-display");
37636 Fput (Qglyphless_char_display, Qchar_table_extra_slots, make_fixnum (1));
37637
37638 DEFVAR_LISP ("glyphless-char-display", Vglyphless_char_display,
37639 doc:
37640
37641
37642
37643
37644
37645
37646
37647
37648
37649
37650
37651
37652
37653
37654
37655
37656
37657
37658
37659
37660
37661
37662
37663 );
37664 Vglyphless_char_display = Fmake_char_table (Qglyphless_char_display, Qnil);
37665 Fset_char_table_extra_slot (Vglyphless_char_display, make_fixnum (0),
37666 Qempty_box);
37667
37668 DEFVAR_LISP ("debug-on-message", Vdebug_on_message,
37669 doc: );
37670 Vdebug_on_message = Qnil;
37671
37672 DEFVAR_LISP ("set-message-function", Vset_message_function,
37673 doc:
37674
37675
37676
37677
37678
37679
37680
37681
37682
37683 );
37684 Vset_message_function = Qnil;
37685
37686 DEFSYM (Qdont_clear_message, "dont-clear-message");
37687 DEFVAR_LISP ("clear-message-function", Vclear_message_function,
37688 doc:
37689
37690
37691
37692
37693
37694
37695
37696
37697
37698
37699 );
37700 Vclear_message_function = Qnil;
37701
37702 DEFVAR_LISP ("redisplay--all-windows-cause", Vredisplay__all_windows_cause,
37703 doc:
37704 );
37705 Vredisplay__all_windows_cause = Fmake_hash_table (0, NULL);
37706
37707 DEFVAR_LISP ("redisplay--mode-lines-cause", Vredisplay__mode_lines_cause,
37708 doc:
37709 );
37710 Vredisplay__mode_lines_cause = Fmake_hash_table (0, NULL);
37711
37712 DEFVAR_BOOL ("redisplay--inhibit-bidi", redisplay__inhibit_bidi,
37713 doc: );
37714
37715
37716 redisplay__inhibit_bidi = true;
37717
37718 DEFVAR_BOOL ("display-raw-bytes-as-hex", display_raw_bytes_as_hex,
37719 doc:
37720
37721 );
37722 display_raw_bytes_as_hex = false;
37723
37724 DEFVAR_BOOL ("mouse-fine-grained-tracking", mouse_fine_grained_tracking,
37725 doc:
37726
37727 );
37728 mouse_fine_grained_tracking = false;
37729
37730 DEFVAR_BOOL ("tab-bar--dragging-in-progress", tab_bar__dragging_in_progress,
37731 doc: );
37732 tab_bar__dragging_in_progress = false;
37733
37734 DEFVAR_BOOL ("redisplay-skip-initial-frame", redisplay_skip_initial_frame,
37735 doc:
37736
37737
37738
37739 );
37740 redisplay_skip_initial_frame = true;
37741
37742 DEFVAR_BOOL ("redisplay-skip-fontification-on-input",
37743 redisplay_skip_fontification_on_input,
37744 doc:
37745
37746
37747
37748
37749
37750
37751
37752 );
37753 redisplay_skip_fontification_on_input = false;
37754
37755 DEFVAR_BOOL ("redisplay-adhoc-scroll-in-resize-mini-windows",
37756 redisplay_adhoc_scroll_in_resize_mini_windows,
37757 doc:
37758
37759 );
37760
37761 redisplay_adhoc_scroll_in_resize_mini_windows = true;
37762
37763 DEFVAR_BOOL ("composition-break-at-point", composition_break_at_point,
37764 doc:
37765
37766 );
37767 composition_break_at_point = false;
37768
37769 DEFVAR_INT ("max-redisplay-ticks", max_redisplay_ticks,
37770 doc:
37771
37772
37773
37774
37775
37776
37777
37778
37779
37780
37781
37782 );
37783 max_redisplay_ticks = 0;
37784 }
37785
37786
37787
37788
37789 void
37790 init_xdisp (void)
37791 {
37792 CHARPOS (this_line_start_pos) = 0;
37793
37794 echo_area_window = minibuf_window;
37795
37796 if (!noninteractive)
37797 {
37798 struct window *m = XWINDOW (minibuf_window);
37799 Lisp_Object frame = m->frame;
37800 struct frame *f = XFRAME (frame);
37801 Lisp_Object root = FRAME_ROOT_WINDOW (f);
37802 struct window *r = XWINDOW (root);
37803 int i;
37804
37805 r->top_line = FRAME_TOP_MARGIN (f);
37806 r->pixel_top = r->top_line * FRAME_LINE_HEIGHT (f);
37807 r->total_cols = FRAME_COLS (f);
37808 r->pixel_width = r->total_cols * FRAME_COLUMN_WIDTH (f);
37809 r->total_lines = FRAME_TOTAL_LINES (f) - 1 - FRAME_MARGINS (f);
37810 r->pixel_height = r->total_lines * FRAME_LINE_HEIGHT (f);
37811
37812 m->top_line = FRAME_TOTAL_LINES (f) - 1;
37813 m->pixel_top = m->top_line * FRAME_LINE_HEIGHT (f);
37814 m->total_cols = FRAME_COLS (f);
37815 m->pixel_width = m->total_cols * FRAME_COLUMN_WIDTH (f);
37816 m->total_lines = 1;
37817 m->pixel_height = m->total_lines * FRAME_LINE_HEIGHT (f);
37818
37819 scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
37820 scratch_glyph_row.glyphs[TEXT_AREA + 1]
37821 = scratch_glyphs + MAX_SCRATCH_GLYPHS;
37822
37823
37824 for (i = 0; i < 3; ++i)
37825 default_invis_vector[i] = make_fixnum ('.');
37826 }
37827
37828 {
37829
37830
37831 int size = 100;
37832 mode_line_noprop_buf = xmalloc (size);
37833 mode_line_noprop_buf_end = mode_line_noprop_buf + size;
37834 mode_line_noprop_ptr = mode_line_noprop_buf;
37835 mode_line_target = MODE_LINE_DISPLAY;
37836 }
37837
37838 help_echo_showing_p = false;
37839 }
37840
37841 #ifdef HAVE_WINDOW_SYSTEM
37842
37843
37844
37845
37846
37847 static void
37848 show_hourglass (struct atimer *timer)
37849 {
37850
37851
37852
37853 hourglass_atimer = NULL;
37854
37855 if (!hourglass_shown_p)
37856 {
37857 Lisp_Object tail, frame;
37858
37859 block_input ();
37860
37861 FOR_EACH_FRAME (tail, frame)
37862 {
37863 struct frame *f = XFRAME (frame);
37864
37865 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
37866 && FRAME_RIF (f)->show_hourglass)
37867 FRAME_RIF (f)->show_hourglass (f);
37868 }
37869
37870 hourglass_shown_p = true;
37871 unblock_input ();
37872 }
37873 }
37874
37875
37876
37877 void
37878 start_hourglass (void)
37879 {
37880 struct timespec delay;
37881
37882 cancel_hourglass ();
37883
37884 if (FIXNUMP (Vhourglass_delay)
37885 && XFIXNUM (Vhourglass_delay) > 0)
37886 delay = make_timespec (min (XFIXNUM (Vhourglass_delay),
37887 TYPE_MAXIMUM (time_t)),
37888 0);
37889 else if (FLOATP (Vhourglass_delay)
37890 && XFLOAT_DATA (Vhourglass_delay) > 0)
37891 delay = dtotimespec (XFLOAT_DATA (Vhourglass_delay));
37892 else
37893 delay = make_timespec (DEFAULT_HOURGLASS_DELAY, 0);
37894
37895 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
37896 show_hourglass, NULL);
37897 }
37898
37899
37900
37901
37902 void
37903 cancel_hourglass (void)
37904 {
37905 if (hourglass_atimer)
37906 {
37907 cancel_atimer (hourglass_atimer);
37908 hourglass_atimer = NULL;
37909 }
37910
37911 if (hourglass_shown_p)
37912 {
37913 Lisp_Object tail, frame;
37914
37915 block_input ();
37916
37917 FOR_EACH_FRAME (tail, frame)
37918 {
37919 struct frame *f = XFRAME (frame);
37920
37921 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
37922 && FRAME_RIF (f)->hide_hourglass)
37923 FRAME_RIF (f)->hide_hourglass (f);
37924 #ifdef HAVE_NTGUI
37925
37926 else if (!FRAME_W32_P (f))
37927 w32_arrow_cursor ();
37928 #endif
37929 }
37930
37931 hourglass_shown_p = false;
37932 unblock_input ();
37933 }
37934 }
37935
37936
37937
37938
37939
37940
37941
37942
37943 static int
37944 adjust_glyph_width_for_mouse_face (struct glyph *g, struct glyph_row *row,
37945 struct window *w,
37946 struct face *original_face,
37947 struct face *mouse_face)
37948 {
37949 int sum = 0;
37950
37951 bool do_left_box_p = g->left_box_line_p;
37952 bool do_right_box_p = g->right_box_line_p;
37953
37954
37955
37956 if (g->type == IMAGE_GLYPH)
37957 {
37958 if (!row->reversed_p)
37959 {
37960 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
37961 g->u.img_id);
37962 do_left_box_p = g->left_box_line_p &&
37963 g->slice.img.x == 0;
37964 do_right_box_p = g->right_box_line_p &&
37965 g->slice.img.x + g->slice.img.width == img->width;
37966 }
37967 else
37968 {
37969 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
37970 g->u.img_id);
37971 do_left_box_p = g->left_box_line_p &&
37972 g->slice.img.x + g->slice.img.width == img->width;
37973 do_right_box_p = g->right_box_line_p &&
37974 g->slice.img.x == 0;
37975 }
37976 }
37977
37978
37979 if (do_left_box_p)
37980 sum -= max (0, original_face->box_vertical_line_width);
37981
37982
37983 if (do_right_box_p)
37984 sum -= max (0, original_face->box_vertical_line_width);
37985
37986 if (g->left_box_line_p)
37987 sum += max (0, mouse_face->box_vertical_line_width);
37988 if (g->right_box_line_p)
37989 sum += max (0, mouse_face->box_vertical_line_width);
37990
37991 return sum;
37992 }
37993
37994
37995
37996
37997
37998
37999
38000
38001
38002 static void
38003 get_cursor_offset_for_mouse_face (struct window *w, struct glyph_row *row,
38004 int *offset)
38005 {
38006 int sum = 0;
38007
38008 if (row->mode_line_p)
38009 return;
38010
38011 block_input ();
38012
38013 struct frame *f = WINDOW_XFRAME (w);
38014 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
38015 struct glyph *start, *end;
38016 struct face *mouse_face = FACE_FROM_ID (f, hlinfo->mouse_face_face_id);
38017 int hpos = w->phys_cursor.hpos;
38018 end = &row->glyphs[TEXT_AREA][hpos];
38019
38020 if (!row->reversed_p)
38021 {
38022 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
38023 hlinfo->mouse_face_beg_row)
38024 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_beg_col];
38025 else
38026 start = row->glyphs[TEXT_AREA];
38027 }
38028 else
38029 {
38030 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
38031 hlinfo->mouse_face_end_row)
38032 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_end_col];
38033 else
38034 start = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
38035 }
38036
38037
38038
38039
38040 for ( ; row->reversed_p ? start > end : start < end;
38041 row->reversed_p ? --start : ++start)
38042 sum += adjust_glyph_width_for_mouse_face (start, row, w,
38043 FACE_FROM_ID (f, start->face_id),
38044 mouse_face);
38045
38046 if (row->reversed_p)
38047 sum = -sum;
38048
38049 *offset = sum;
38050
38051 unblock_input ();
38052 }
38053 #endif